Políticas de repetición y backoff
Las repeticiones (retries) ayudan a sobrevivir a fallas temporales, pero cuando se configuran incorrectamente provocan avalanchas de tráfico, tomas de operaciones y caídas en cascada. Una política de retraídas fiable siempre comienza con deduplines/timeouts, tiene en cuenta la idempotencia y utiliza backoff + jitter.
1) Principios básicos
1. Primero Taimout/Deadline, luego Retray. La repetición sin límite de tiempo solo alarga el rechazo.
2. Retray - sólo para operaciones seguras/idempotentes. Para los inseguros - a través de idempotency-keys y garantías transaccionales.
3. Backoff es obligatorio. Exponencial o GCRA-similar con el jitter para dispersar las ondas.
4. Limite el número de intentos y el tiempo total del presupuesto. No vaya al SLO del usuario.
5. Respeta las señales de la infraestructura. '429/503' + 'Retry-After', el estado del circuito breaker, límites de colas.
2) Timeouts y deadline (deadline propagation)
El tiempo de espera de la solicitud <SLO del servicio, el tiempo de espera se distribuye por la cadena (encabezados HTTP/gRPC context).
Composición de temporizadores: sumario (primer intento + backoff + posterior) ≤ deadline personalizado.
Diferentes temporizadores para lecturas/grabaciones: las entradas son más cortas y estrictas; las lecturas permiten hedging.
3) Idempotencia y repeticiones seguras
Lecturas (GET/idempotent RPC): es seguro repetir con '5xx', 'UNAVAILABLE', temporizadores de red.
Registros:- Utilice 'Idempotency-Key' (HTTP) o request-ID en el borde; el servidor debe deduplicar.
- Escribir manejadores idempotentes: «upsert», «at-least-once» + compensación (saga).
- Pagos externos/pagos recíprocos - sólo con claves idempotentes y registro de transacciones.
4) Algoritmos backoff
Exponential: 'base 2 ^ attempt', restringido a' max _ backoff '.
Jitter decorrelado (full/equal jitter): aleatoriedad en el rango para la resincronización de clientes.
GCRA/Token-Bucket-tales retrasos: acordados con los límites de la tasa.
Bordes: 'initial _ backoff' (50-200 ms de lectura; 200-500 ms de grabación), 'max _ backoff' (1-5 s), 'max _ elapsed' (por ejemplo, 3-10 s).
Plantilla recomendada: backoff exponencial + full jitter.
5) Políticas para decidir «repetir/no repetir»
Repetimos cuando:- Errores de red/temporización, '429' (respetando 'Retry-After'), 'blando' '5xx' ('502/503/504'), gRPC 'UNAVAILABLE/DEADLINE _ EXCEEDED'.
- '4xx' (excepto '409/429/408' en algunos escenarios), errores empresariales, '401/403', errores de validación, bandera explícita 'DoNotRetry'.
- '409 Conflict' es a veces una repetición con retraso después del consenso/locks.
- '404' para lecturas consistentes eventuales es un retray de una a dos veces con un pequeño backoff.
6) Concurrency caps y «tormenta de retraídos»
Limite los retratos simultáneos per-client/per-tenant/per-endpoint.
Límite total de intentos de consulta (por ejemplo, 2-3).
Frena los puntos de endpoints «calientes» a través del control de admisión para no inflar las colas.
7) Interacción con Circuit Breaker y límites
Si CB está abierto, no realice retraídas directamente - vaya a fallback o espere muestras 'half-open'.
Con '429' - respeta 'Retry-After'; si no está presente, aplique un backoff «suave».
Los retraídos pueden aumentar la carga; aplicar umbrales adaptativos (reducir 'max _ attempts' en caso de incidente).
8) Protocolos y contratos
HTTP
Códigos: '408/429/5xx'.
Titulares: 'Retry-After', de la familia 'RateLimit-', 'Idempotency-Key', 'Request-Id'.
El cliente debe transmitir 'X-Request-Timeout '/' Deadline-At' (si así lo acepta).
gRPC
Utilice el contexto con el Depline; respeta 'UNAVAILABLE', 'DEADLINE _ EXCEEDED', pólizas de retraídas por método.
Para los RPC idempotentes: incluya retraídas; para mutaciones - sólo con el apoyo de la idempotencia.
9) Colas, tareas de fondo e integraciones
Controladores At-least-once → acciones idempotentes, deduplicación por clave.
Delay queue para backoff entre intentos (por ejemplo, 5s/30s/2m).
Cola de carta muerta (DLQ) con límite de intento y manejo manual.
Outbox/CDC - para que las repeticiones no violen la integridad transaccional.
10) Hedging vs Retries
Hedging (consulta de espejo) es útil para lecturas altamente críticas en latencia de cola.
Limite: no más de X% de las solicitudes, retraso «start-grace» (por ejemplo, latencia p95), cancelación de perdedores.
No aplique hedging a operaciones de escritura sin una fuerte idempotencia.
11) Telemetría y observabilidad
Теги: `tenant_id`, `endpoint`, `attempt`, `decision` (retry/skip), `reason`, `backoff_ms`, `deadline_ms`, `idempotency_key`.
Métricas: proporción de retraídas, éxito después de retraídas, p95/p99 "end-to-end', número de dedlines superados, CB activado.
Registros de auditoría: N «ruidosas» llaves/endpoints superiores, correlación con 429/503.
12) Pruebas y caos
Perfiles: «saw» (calma burst), «storm» (timautas masivos), errores «pegajosos» (cada N.o), colas de latencia.
Fallas del Split Limiter/caché/cola, clock-skew.
Comprobar que la duración total (attempts + backoff) se ajusta al SLO.
13) Pseudocódigo de política
pseudo handle(req, deadline):
attempt = 0 backoff = initial()
while attempt < MAX_ATTEMPTS and now() < deadline:
attempt += 1 with timeout(per_attempt_timeout(deadline, attempt)):
try:
resp = call(req)
if isRetryableStatus(resp): raise Retryable(resp. status)
return resp except Retryable as e:
if circuit. isOpen(dep) or! isIdempotent(req): break sleep(jitter(backoff))
backoff = min(exp(backoff), MAX_BACKOFF)
except NonRetryable:
break return fail_or_fallback(req)
14) Plantilla de configuración (ejemplo)
yaml retries:
default:
max_attempts: 3 initial_backoff_ms: 150 max_backoff_ms: 2000 strategy: exponential_full_jitter respect_retry_after: true per_attempt_timeout_fraction: 0. 4 # 40% of remaining deadline hedging:
enabled: false read_heavy:
max_attempts: 4 initial_backoff_ms: 80 max_backoff_ms: 1200 hedging:
enabled: true start_after_p95_ms: 300 max_extra_requests_ratio: 0. 05 write_strict:
max_attempts: 2 initial_backoff_ms: 250 max_backoff_ms: 1000 idempotency_required: true
limits:
concurrent_retries_per_tenant: 100 concurrent_retries_per_endpoint: 20
15) Lista de verificación antes de la venta
- Los deadline se propagan a través de las llamadas; duración total de ≤ SLO.
- Algoritmo backoff con jitter; parámetros validados por la prueba de carga.
- Idempotencia: claves/registros/compensación para los registros.
- Las políticas de retransmisión varían para lecturas y registros; respect `Retry-After`.
- La competencia de los retiros y el número total de intentos son limitados.
- La integración con circuit breaker y rate limits está configurada.
- Telemetría: etiquetas, métricas, registros de causa; dashboards p95/p99, una fracción de los éxitos después de los retiros.
- Pruebas de «tormentas» y colas de latencia, DLQ para tareas.
- Documentación para clientes: códigos/encabezados, ejemplos de backoff y cancelaciones.
16) Errores típicos
Las repeticiones sin timeouts/dedlines son «expectativas eternas».
Pausas fijas sin jitter: ondas sincrónicas y autosabotaje DDoS.
Los retratos de registros inseguros sin idempotencia son tomas y resincronización.
Ignorar 'Retry-After' y las señales CB es una escalada del incidente.
Cuellos de botella en las colas por falta de caps y control de admision.
La falta de telemetría de las causas/decisiones de los retraídos es un «vuelo ciego».
17) Recetas rápidas
API de lectura pública: 3 intentos, 'initial = 100ms', 'max = 1s', full jitter, hedging hasta el 5% del tráfico.
Registros críticos (pago): 1-2 intentos max, tiempo de espera estricto, obligatorio 'Idempotency-Key', sin hedging.
Integraciones externas: respetar '429/Retry-After', 'max _ attempts = 3', 'max _ backoff = 2-5s', límites al flujo saliente.
Tareas de fondo: delay-backoff (5s → 30s → 2m), DLQ, manejadores idempotentes.
Conclusión
Una buena política de repetición es el equilibrio entre la recuperación inminente y el fracaso controlado. Los deadlines, la idempotencia, el retroceso exponencial con jitter, la restricción de la competencia y el respeto a las señales de infraestructura convierten a los retraídos de una «tormenta» en una herramienta para mejorar la fiabilidad y retención de SLO.