GH GambleHub

Circuit Breaker y retiros

Circuit Breaker y Retray

1) Por qué es necesario

Las redes no son fiables: la latencia pulsa, los nodos caen, se alcanzan los límites. Los retiros se salvan de fallos a corto plazo, mientras que Circuit Breaker protege el sistema de fallos en cascada y «uno mismo-DDoS». La combinación con los timeouts y límites correctos mantiene el SLO, estabiliza los retrasos de cola y el precio de la «novena».

2) Principios básicos

Primero los timautas, después los retraídos, luego el Circuit Breaker.
Retraim sólo operaciones idempotentes (GET, seguro POST/PUT con clave idempotente).
Asigne un presupuesto para retiros: ≤ el 10-15% del RPS original por ruta.
Localice el fallo: bulkhead (agrupaciones/cuotas separadas) + rate-limit.
En la degradación: falla rápida (fail-fast), degradación graceful/enchufes.

3) Semántica de retraídas

Cuándo retirar

Errores transitorios: timeouts, 5xx, inaccesibilidad de red, 429 (después de 'Retry-After').
No se puede retractar: errores empresariales explícitos (4xx ≠ 429), efectos laterales sin idempotencia (pago sin clave).

Estrategias

Retroceso exponencial + jitter (completo o uniforme): suaviza las bandadas de retraídos.
Máx attempts: 1-2 (raramente 3) - más generalmente perjudicial.
Budget: contador global de retrayas/segundos por servicio y per-request «retry tokens».
Hedging (raramente): toma de consulta paralela después de t-cuantili (p95) - sólo para lecturas estrictamente idempotentes.

Alias backoff + jitter:
python base = 100 # ms for attempt in range(1, max_attempts+1):
try:
return call()
except Transient as e:
if attempt == max_attempts: raise sleep_ms = min(cap_ms, base 2(attempt-1))
sleep(random(0, sleep_ms)) # full jitter

4) Taimauts y «fracaso rápido»

Client timeout <upstream timeout: para no cavar solicitudes "zombis'.
Делите: connect timeout, read timeout, overall deadline.
Tail-aware Timeout: apuntamos a p95/p99 + pequeño stock.
Utilice un campo deadline común (por ejemplo, gRPC 'deadline') y colóquelo por la cadena.

5) Circuit Breaker: cómo funciona

Estados:
  • Cerrado: omite tráfico, cuenta errores/latencia.
  • Abierto: inmediatamente da un fallo rápido (o respuesta de repuesto).
  • Half-Open: solicitudes de verificación; si tiene éxito, se cierra.
Umbral de apertura:
  • Los errores/temporizaciones superan la proporción de X% por la ventana N de consultas/segundos o p99 por encima del umbral.
  • Las estadísticas deslizantes y el volumen mínimo (por ejemplo, ≥ 50 consultas) son relevantes.

6) Bulkhead, cuotas y «dividir y dominar»

Pullos separados de las conexiones per-upstream y per-fich.
Cuotas de consultas en vuelo; una falla extra - rápida.
En caso de escasez, la degradación es un fich de baja prioridad (flags feature).

7) Integración perimetral (Envoy/Istio/Nginx)

Envoy (retry + outlier + CB, idea):
yaml routes:
- match: { prefix: "/api" }
route:
cluster: upstream_api timeout: 2s retry_policy:
retry_on: "connect-failure,reset,retriable-4xx,5xx"
num_retries: 2 per_try_timeout: 600ms retry_back_off: { base_interval: 100ms, max_interval: 800ms }
hedge_policy:
hedge_on_per_try_timeout: true initial_requests: 1 additional_request_chance: { numerator: 5, denominator: HUNDRED } # 5%
clusters:
- name: upstream_api circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 500 max_requests: 1000 max_retries: 200 outlier_detection:
consecutive_5xx: 5 interval: 5s base_ejection_time: 30s max_ejection_percent: 50
Istio (VirtualService fault/retry, ejemplo comprimido):
yaml apiVersion: networking. istio. io/v1beta1 kind: VirtualService spec:
hosts: ["payments"]
http:
- route: [{ destination: { host: payments } }]
timeout: 2s retries:
attempts: 2 perTryTimeout: 600ms retryOn: "5xx,connect-failure,refused-stream,reset"
Nginx Ingress (anotaciones):
yaml nginx. ingress. kubernetes. io/proxy-connect-timeout: "2"
nginx. ingress. kubernetes. io/proxy-read-timeout: "2"
nginx. ingress. kubernetes. io/proxy-next-upstream: "error timeout http_502 http_503 http_504"
nginx. ingress. kubernetes. io/proxy-next-upstream-tries: "2"

8) Bibliotecas y código (stack-snippets)

Java (Resilience4j):
java var cb = CircuitBreaker. ofDefaults("psp");
var retry = Retry. of("psp-retry",
RetryConfig. custom()
.maxAttempts(2)
.waitDuration(Duration. ofMillis(200))
.intervalFunction(IntervalFunction. ofExponentialRandomBackoff(100, 2. 0, 0. 5) )//jitter
.retryExceptions(SocketTimeoutException. class, IOException. class)
.build());

Supplier<Response> decorated =
CircuitBreaker. decorateSupplier(cb,
Retry. decorateSupplier(retry, () -> client. call()));

return Try. ofSupplier(decorated)
.recover(BusinessException. class, fallback())
.get();
Go (context deadline + backoff):
go ctx, cancel:= context. WithTimeout(context. Background(), 2time. Second)
defer cancel()
var lastErr error for i:= 0; i < 2; i++ {
reqCtx, stop:= context. WithTimeout(ctx, 600time. Millisecond)
lastErr = call(reqCtx)
stop()
if lastErr == nil { break }
sleep:= time. Duration(rand. Intn(1<<uint(7+i))) time. Millisecond // full jitter time. Sleep(min(sleep, 800time. Millisecond))
}
if lastErr!= nil { return fastFail() }
Node. js (got + p-retry):
js import pRetry from 'p-retry';
await pRetry(() => got(url, { timeout: { connect: 500, request: 2000 } }), {
retries: 2,
factor: 2,
randomize: true,
minTimeout: 100,
maxTimeout: 800,
onFailedAttempt: e => { if (isBusiness(e)) throw e; }
});

9) Presupuesto para retiros y SLO

Escriba retry tokens: cada retray gasta un token; la agrupación está limitada.
Conecte con error-budget: cuando burn-rate está por encima del umbral - desactivar retraídas, abrir CB más a menudo, activar la degradación.
Lanzamientos canarios: en Canarias, reducir los intentos y fichajes.

10) Hedging (cuidado)

Ejecute una solicitud adicional después del p95-deduble, cancelando al perdedor.
Sólo para lecturas y operaciones idempotentes «seguras»; limite la participación (≤ 1-5%).
Observe el aumento de la carga de Apstream.

11) Observabilidad

Métricas rojas en las rutas: Tasa, Error, Duración (p50/p95/p99).
Métricas CB: estado (abierto/medio-abierto), frecuencia de apertura, solicitudes omitidas/denegadas.
Retrai: attempts/request, retry-rate, tokens quemados.
Perímetro: outlier-ejection, ejection-rate.
Tracks: anote 'retry _ attempt',' cb _ state ',' hedged = true ', haga clic en' trace _ id '.

12) Integración con la arquitectura

Bulkhead + CB para cada Apstream crítico.
Colas/asinchron: para operaciones largas en lugar de temporizadores locos.
Caché/tapones: para fiches no críticos en fail-open.
Auto Scale: no compensa los malos retraídos - primero detenga la «tormenta».

13) Anti-patrones

Los retiros sin taimautas → los connects «colgantes» y el agotamiento de las piscinas.
Repetición de operaciones no idempotentes (doble cargo).
Crecimiento exponencial infinito sin cap y jitter.
Un único CB a todos los Apstrips → arrastrar y soltar el fallo a todo el producto.
Ignorar 429/' Retry-After '.
El tiempo de espera del cliente es más largo que el tiempo de espera (o no en absoluto).
«Tratar» los errores de negocio con retraídas.

14) Lista de verificación de implementación (0-30 días)

0-7 días

Identificar las rutas y su idempotencia.
Defina los temporizadores (connect/read/overall), habilite los retratos mínimos (× 1) y CB predeterminados.
Separe los grupos/cuotas (bulkhead) para los apstreams principales.

8-20 días

Habilite el jitter y el presupuesto global de retrés, alertas por retry-rate.
Ajuste el outlier-ejection en el perímetro, fallo rápido para low-prio fich.
Dashboards RED + CB/Retry, tracks etiquetados.

21-30 días

Los perfiles canarios son retraídos (menos intentos), el game-day es «upstream slow/flaping».
Documentar la política: quién/qué retrae, límites, excepciones.
Revise p95/p99 y los timeouts según los datos, no a la vista.

15) Métricas de madurez

El 100% de las rutas tienen timautas y una política de retraídas/SV documentada.
Retry-rate se ajusta al presupuesto (≤ 10-15%), no hay picos en incidentes.
Los CB se activan antes de que caiga toda la piscina; no hay fallos en cascada.
Los tracks muestran intentos/hedging; p99 estable en picos.
Los lanzamientos canarios utilizan un perfil «cuidadoso» de retraídos.

16) Ejemplos cortos de configuraciones

Resilience4j YAML (Spring Boot, идея):
yaml resilience4j:
circuitbreaker:
instances:
psp:
slidingWindowType: COUNT_BASED slidingWindowSize: 100 minimumNumberOfCalls: 50 failureRateThreshold: 50 waitDurationInOpenState: 30s permittedNumberOfCallsInHalfOpenState: 5 retry:
instances:
psp:
maxAttempts: 2 waitDuration: 200ms enableExponentialBackoff: true exponentialBackoffMultiplier: 2. 0 retryExceptions:
- java. net. SocketTimeoutException
- java. io. IOException
Envoy rate-limit (fragmento de idea):
yaml rate_limits:
- actions:
- generic_key: { descriptor_value: "api. payments" }

17) Conclusión

La sostenibilidad es una disciplina: timeouts → retiros (con jitter y presupuesto) → Circuit Breaker + bulkhead/cupos y fracaso rápido. Configure el perímetro (outlier-ejection), cuelgue los dashboards RED/CB/Retry, fije la política de idempotencia y recuerde el SLI empresarial. Entonces, los breves fallos permanecerán invisibles, y los incidentes reales no se convertirán en caídas en cascada.

Contact

Póngase en contacto

Escríbanos ante cualquier duda o necesidad de soporte.¡Siempre estamos listos para ayudarle!

Telegram
@Gamble_GC
Iniciar integración

El Email es obligatorio. Telegram o WhatsApp — opcionales.

Su nombre opcional
Email opcional
Asunto opcional
Mensaje opcional
Telegram opcional
@
Si indica Telegram, también le responderemos allí además del Email.
WhatsApp opcional
Formato: +código de país y número (por ejemplo, +34XXXXXXXXX).

Al hacer clic en el botón, usted acepta el tratamiento de sus datos.