01El fallo es inevitable — diseñar para absorberlo
⚠️
La premisa fundamental de la resiliencia
En sistemas distribuidos, no preguntes "¿fallará el servicio B?" — sino "¿cuándo fallará y cómo respondo?" La red falla. Los discos fallan. Los procesos se reinician. Un sistema resiliente no es el que nunca falla, sino el que está diseñado para fallar de forma controlada y recuperarse sin intervención humana.
Límite de esperaFail fastConnection timeout
Define el tiempo máximo que un servicio espera respuesta de otro antes de declarar el fallo. Sin timeout, un hilo puede quedarse bloqueado indefinidamente — agotando el pool de conexiones y propagando el fallo en cascada.
Dos tipos:
Connection timeout: tiempo para establecer la conexión TCP (~2s).
Read timeout: tiempo esperando la respuesta una vez conectado. Calibra con el p99 de latencia del servicio dependiente.
Un timeout demasiado largo propaga el fallo. Uno muy corto genera falsos negativos. Mide el p99 de latencia y usa ese valor como referencia.
ReintentosIdempotenteMax attempts
Reintenta automáticamente una operación fallida. Solo seguro cuando la operación es idempotente — ejecutarla N veces produce el mismo resultado que 1 vez. Sin idempotencia, los retries crean duplicados.
Regla: Reintenta errores transitorios (503, 429, timeout). Nunca reintentes errores de negocio (400, 404, 422) — si el request está mal formado, reintentar es inútil y nocivo.
Define siempre un máximo de reintentos. Un retry infinito en cascada puede convertir un fallo puntual en una tormenta de tráfico.
🎲
PATRÓN 3
Jitter — Exponential Backoff
Ruido aleatorioThundering herdBackoff
Añade retraso aleatorio a cada reintento. Sin jitter, cientos de clientes reintentan en sincronía y rematan al servicio caído (efecto manada / thundering herd).
Fórmula Full Jitter (AWS):
sleep = random(0, min(cap, base × 2^attempt))
Intento 1: ~100ms
Intento 2: ~200ms
Intento 3: ~400ms
El jitter dispersa los reintentos en el tiempo. Sin él, 500 servicios reintentan a los exactos 2 segundos — con él, se distribuyen en una ventana de 2-3 segundos.
02Circuit Breaker — la máquina de estados que protege el sistema
Máquina de estados del Circuit Breaker
🟢
CLOSED
Funcionando normal
Las llamadas fluyen. El CB cuenta los fallos en una ventana deslizante. Si superan el umbral configurado, el circuito se abre.
fallos > umbral
→
←
timeout expirado
🔴
OPEN
Circuito abierto
Las llamadas se rechazan inmediatamente (fail fast) sin llegar al servicio. El servicio caído puede recuperarse sin presión.
prueba una llamada
→
←
falla de nuevo
🟡
HALF-OPEN
Probando recuperación
Permite un número limitado de llamadas de prueba. Si tienen éxito → CLOSED. Si fallan → OPEN de nuevo.
prueba exitosa ↙
vuelve a CLOSED
Qué monitorear
Tasa de errores en ventana deslizante (ej: >50% en últimos 10s). También latencia alta puede activarlo — no solo errores 5xx.
Qué hacer en OPEN
Retornar respuesta de fallback (valor cacheado, respuesta degradada, error claro). Nunca dejar la llamada colgada sin respuesta.
Implementaciones
Resilience4j (Java), Polly (.NET). En Istio/Envoy se configura sin código en el sidecar.
Resilience4j — CB + Retry + Fallback combinadosJAVA
@Service
public class OrderClient {
// Decorar la llamada — CB fuera, Retry dentro
@CircuitBreaker(name = "orderService", fallbackMethod = "fallback")
@Retry(name = "orderService")
@TimeLimiter(name = "orderService")
public Order getOrder(String id) {
return httpClient.get("/orders/" + id);
}
// Fallback cuando CB está OPEN
private Order fallback(String id, Exception ex) {
log.warn("CB open for order {}", id);
return orderCache.getOrDefault(id, Order.EMPTY);
}
}
Bulkhead — aislamiento de pools de recursos
❌ Sin Bulkhead — pool compartido
20 threads — todos los servicios comparten
B satura los 20 threads → A y C también quedan sin hilos → fallo total.
✅ Con Bulkhead — pools aislados
8 threads → Servicio B ❌ saturado
B falla solo. A y C siguen operando — el barco no se hunde por un mamparo.
03Stack de resiliencia completo — el orden importa
🚢
CAPA 1 — MÁS EXTERNA
Bulkhead
Aísla recursos. Un fallo en un módulo no hunde el barco.
⏱
CAPA 2
Timeout
Libera threads bloqueados. Define el límite de paciencia del sistema.
🔌
CAPA 3
Circuit Breaker
Evita llamadas inútiles. Da tiempo al servicio para recuperarse.
🔁
CAPA 4 — MÁS INTERNA
Retry + Jitter
Recupera fallos transitorios. Jitter evita el efecto manada.
Orden de decoración: Bulkhead → Timeout → Circuit Breaker → Retry (de afuera hacia adentro). El Retry fuera del CB es un error — si el CB está abierto, no tiene sentido reintentar.