Saltar al contenido

Resiliencia en Sistemas Distribuidos

Timeout, retry, circuit breaker, idempotencia, bulkhead, rate limiting, backpressure, load shedding, dead letter queue, saga y degradación controlada: los mecanismos explícitos que necesita un sistema distribuido para convivir con fallos parciales.

9 min. de lectura

Un sistema distribuido cambia por completo el modelo de fallos. En un proceso local, una función puede devolver un resultado o lanzar una excepción. En una interacción remota:

puede suceder que la request nunca llegue, que llegue dos veces, que el Service B procese la operación pero la respuesta se pierda, que el Service B tarde demasiado o que solo una parte del sistema esté fallando. Por eso, una arquitectura distribuida necesita mecanismos explícitos de resiliencia: Timeout, Retry, Circuit Breaker, Idempotencia, Bulkhead, Rate Limiting, Backpressure, Load Shedding, Dead Letter Queue, Saga y Graceful Degradation.

Timeout

Una dependencia nunca debería poder bloquear recursos indefinidamente:

Pero:

Timeout no significa que la operación no haya ocurrido.

Este detalle es crítico:

El cliente ve un timeout. La tarjeta ya fue cobrada.

Retry

Ante fallos transitorios:

Un retry robusto suele considerar backoff exponencial, jitter, cantidad máxima de intentos y un presupuesto de tiempo.

Retry + operación no idempotente

Esto es peligroso:

Por eso Timeout, Retry e Idempotencia deben diseñarse juntos.

Circuit Breaker

Permite dejar de enviar requests a una dependencia que está fallando:

Cuando está OPEN, el sistema puede fallar rápidamente en lugar de acumular timeouts y seguir saturando la dependencia.

Idempotencia

Supongamos:

POST /payments
Idempotency-Key: abc123

En la primera request, el provider crea el payment pero la respuesta se pierde. En la segunda request, con el mismo Idempotency-Key, el sistema reconoce que esa operación ya fue procesada y devuelve el payment existente en lugar de crear uno nuevo:

Es fundamental para payments, orders, webhooks y message consumers.

At-Least-Once Delivery

Muchos sistemas de mensajería utilizan semántica de entrega at-least-once:

Por eso una estrategia práctica es combinar at-least-once con un idempotent consumer.

Bulkhead

Aísla recursos:

Si Notifications se degrada, no debería consumir todos los recursos disponibles para Payments.

Rate Limiting

Controla el flujo entrante:

Protege contra clientes abusivos, picos de tráfico, sobrecarga y clientes que generan tráfico descontrolado de forma accidental. Entre las implementaciones más conocidas están token bucket y leaky bucket.

Backpressure

Supongamos un producer a 20k msg/s y un consumer a 5k msg/s. La diferencia genera acumulación:

Backpressure consiste en hacer que el sistema controle esa diferencia en lugar de aceptar trabajo indefinidamente.

Load Shedding

Cuando el sistema no puede procesar todo:

Es preferible rechazar algunas requests antes que permitir que todo el sistema colapse.

Dead Letter Queue

La DLQ permite inspeccionar mensajes, corregir problemas, reprocesarlos más tarde y evitar que un mensaje defectuoso bloquee la cola de forma permanente.

Saga

Cuando una operación de negocio atraviesa varios servicios, no tenemos una única transacción ACID. Podemos implementar una Saga:

Si Inventory falla, se dispara una cadena de acciones compensatorias:

Graceful Degradation

No todos los componentes deberían tener el mismo nivel de criticidad:

Si Recommendations está caído, Checkout sigue disponible y solo se pierde la funcionalidad de Recommendations. La arquitectura mantiene disponible lo crítico.

Cómo analizar un fallo

Un enfoque práctico es recorrer una serie de preguntas:

Herramientas

Dependiendo de la plataforma: Resilience4j, Envoy, Istio, AWS API Gateway, AWS SQS, Kafka, RabbitMQ, Kubernetes health probes. Las herramientas implementan mecanismos. No reemplazan el diseño de los modos de fallo.

Ninguno de estos mecanismos sirve si no se verifica que funcionan. Un circuit breaker que nunca se abrió en un entorno controlado es una hipótesis, no una protección: hace falta ejercitarlo con performance testing bajo carga y con fallas inyectadas a propósito.

Te sirvió, compartilo

// ¿te sirvió?
// compartilo