Circuito Breaker y degradación
Circuit Breaker (CB) es un patrón de protección que interrumpe las llamadas a una dependencia degradada para localizar el fallo y proteger los servicios de upstream y al usuario. Degradación (graceful degradation): simplificación consciente de la funcionalidad en caso de falta de recursos o fallos (por ejemplo, devolución de datos en caché/incompletos, desactivación de fichas «caras») sin downtime completo.
El objetivo principal: mantener el SLO y la experiencia del usuario a través de fallas controladas, en lugar de caídas en cascada.
1) Cuándo aplicar
La dependencia es inestable: crecimiento p95/p99, tiempos de espera, respuestas erróneas.
API externas con límites rígidos/penalti.
Backends «pesados» (búsquedas, recomendaciones, informes) donde los retraídos amplifican la tormenta.
Áreas altamente cargadas con riesgo de agotamiento de las piscinas (conexiones, hilos).
2) Estados CB y transiciones
Tres clásicos:1. Cerrado - el tráfico va, las métricas de error/latencia cuentan.
2. Abierto: las llamadas se rechazan instantáneamente (fail-fast) y/o se traducen a fallback.
3. Medio-Abierto: un número limitado de consultas de «prueba» determina si cerrar el interruptor.
Desencadenadores de apertura
Umbral de error/temporización por ventana (por ejemplo, ≥ el 50% de N).
Umbral de latencia (por ejemplo, p95> valor objetivo).
Directivas combinadas (errores ∧ exceso de tiempo de espera).
Tiempo de retención (cool-down)
Fijo (por ejemplo, de 10 a 60 segundos) o adaptativo (aumento exponencial en repeticiones).
3) Taimouts, Retrayas y Jitter
Los timeouts son siempre más cortos que los SLO de Apstrim y están alineados por cadena (deadline propagation).
Retraídas sólo para operaciones idempotentes; 1-2 intentos son suficientes en la mayoría de los casos.
Backoff + jitter (full jitter) previene las ondas de repetición sincrónicas.
Hedging (consultas de repuesto): ahorra dinero y sólo para lecturas muy críticas.
4) Bulkhead-aislamiento y «fusibles»
Divida los grupos de conexiones/workers/colas por dominios y tipos de tráfico (VIP, tareas en segundo plano, API públicas).
Caps en concurrency para operaciones «caras».
Control de la administración: falla fácil antes de la ejecución cuando la cola se desborda.
5) Fallback y escenarios de degradación
Opciones
Respuestas de caché/stail: 'stale-while-revalidate', devuelve los datos de la L2/L3 de caché.
Sólo lectura: bloque de escritura/comandos, permitir lecturas seguras.
Respuestas subrogadas: datos incompletos (por ejemplo, sin recomendaciones/avatares).
Desactivación funcional: oculta temporalmente los widgets/fiches no críticos.
Flags de características: cambio de comportamiento rápido sin lanzamiento.
Reglas
Fallback debe ser determinista, rápido y seguro según los datos.
Marca explícitamente el camino degradado en los logs/tries/métricas.
6) Priorización y tráfico de shaping
Planes VIP/pagados: mayor prioridad/cuota en caso de déficit.
Rate limits y throttling reducen la carga en las dependencias degradadas.
Shed load: reducción suave de la calidad (por ejemplo, menos resultados, imágenes cortadas) antes de la estabilización.
7) Observabilidad y señalización
Métricas CB
Estado (cerrado/abierto/medio-abierto) y duración en estado.
Porcentaje de fallos por razones: CB-open, timeout, 5xx, retry-exhausted.
p95/p99 latencia «antes» y «después» del interruptor.
Col-v/porcentaje de consultas a través de fallback.
Anotaciones de Spans: 'circuit = opened', 'fallback = cache', 'admission = denied'.
Correlación con límites (429/RateLimit-), colas y balas de conexión.
Registros/auditorías
Causa de apertura/cierre, umbrales, identificadores de dependencia.
8) Contratos y protocolo
HTTP
Fail-fast: '503 Service Unavailable' con 'Retry-After' (o '429' con límites).
Contenido parcial/file: '200 '/' 206' con metadatos de degradación (por ejemplo, 'X-Degraded: true').
Políticas de caché: 'Cache-Control: stale-if-error, stale-while-revalidate'.
gRPC
'UNAVAILABLE', 'DEADLINE _ EXCEEDED', semántica de retraídas por pólizas cliente/proxy.
Deadline/timeout en el contexto de la solicitud; propagación de la línea de salida por la cadena.
Idempotencia
'Idempotency-Key' para operaciones POST, deduplicación en la frontera.
9) Implementación tipo (pseudocódigo)
pseudo onRequest(req):
if circuit. isOpen(dep):
return fallbackOrFail(req)
with timeout(T):
try:
resp = call(dep, req)
circuit. recordSuccess(dep, latency=resp. latency)
return resp except TimeoutError or 5xx as e:
circuit. recordFailure(dep)
if circuit. shouldOpen(dep):
circuit. open(dep, coolDown=adaptive())
return fallbackOrFail(req)
Prueba Half-Open
pseudo onTimer():
if circuit. state(dep) == OPEN and coolDownExpired():
circuit. toHalfOpen(dep)
onRequestHalfOpen(req):
if circuit. allowTrial (dep): # e.g. 1 try: call -> success => close catch: reopen with longer coolDown else:
return fallbackOrFail(req)
10) Configuración de umbrales
Ventana de observación: deslizamiento N segundos/consultas.
Umbral de error: 20-50% en la ventana (depende del perfil).
Umbral de latencia: p95 ≤ SLO objetivo (por ejemplo, 300-500 ms); el exceso se contabiliza como «error» para CB.
Cool-down adaptativo: 10s → 30s → 60s en re-activaciones.
11) Pruebas y prácticas de caos
Chaos: inyección de latencia/error en función, rotura de DNS, drop packs.
Días de juego: inicio de la «apertura» del interruptor en un entorno similar a la cabeza, comprobación de fallback.
Canarias: habilite las políticas de degradación de SV en primer lugar para el 1-5% del tráfico.
Presupuesto de SLO: permite experimentos hasta que se agote el error-budget.
12) Integración con multi-tenencia
El estado de CB se puede almacenar per-dependency per-tenant (para inquilinos ruidosos) o globalmente - dependiendo del perfil de carga.
Los datos fallback y cachés segmentan por 'tenant _ id'.
Prioridades/cuotas - según los planes (los VIP no deben sufrir el comportamiento de Starter).
13) Lista de verificación antes de la venta
- Los timeouts y los deduplines son de extremo a extremo y coherentes.
- Los retraídos son limitados, solo para operaciones idempotentes, con backoff + jitter.
- Los umbrales CB están justificados por los datos de la prueba de carga.
- Las rutas fallback existen, rápidas y seguras; la caché de directivas está definida.
- Aislamiento de Bulkhead: grupos/colas/límites separados.
- Métricas/tracks/logs marcan la degradación y los estados de CB.
- Documentación de contratos de respuesta (HTTP/gRPC) con ejemplos de encabezados/códigos.
- Los escenarios de caos y los días de juego tienen lugar regularmente; hay un runbook.
14) Errores típicos
No hay taimautas → retraídas «a tope» y caídas en cascada.
Un CB global único en lugar de uno selectivo (por endpoint/método) son fallos superfluos.
El interruptor abierto sin fallback → pantallas «en blanco» en lugar de UX degradado.
Retiros sin jitter → tormentas sincrónicas de consultas.
Largo cool-down en fallos a corto plazo o demasiado corto en estados estables - «flip flop».
La ausencia de bulkhead es el agotamiento de las piscinas comunes y el «bloqueo de cabeza de línea».
15) Selección rápida de la estrategia
Lecturas de alta importancia: CB + caché de respuestas stale + hedging (ahorros).
Registros/pagos: tiempos de espera estrictos, mínimo de retiros, llaves de idempotencia, ausencia de fallback «sucio».
API externos: CB con umbrales agresivos, cool-down adaptativo, trottling estricto.
Microservicios con carga pulsante: bulkheads, caps on concurrency, priorización VIP.
El Circuit Breaker y la degradación gestionada es el «seguro» de la arquitectura: traducen fallas caóticas en comportamientos predecibles. Los timeouts claros, los retraídos limitados con jitter, los pools aislados, las vías fallback pensadas y la telemetría hacen que el sistema sea resistente a las fallas de las dependencias y mantienen el SLO incluso en períodos de pico y emergencia.