GH GambleHub

Timeout и circuit control

1) Pourquoi est-ce nécessaire

Les systèmes ne tombent pas d'une seule défaillance « fatale », mais d'une accumulation de retards et de rétrogrades « vagues ». Les délais limitent les temps d'attente et libèrent des ressources, et le contrôle de circuit (breaker + shedding + concurrence adaptative) empêche la dégradation de se propager le long de la chaîne de dépendance. L'objectif est de maintenir p95/p99 dans les limites des cibles et de maintenir l'accessibilité en cas de défaillance partielle.


2) Définitions de base

2. 1 Types de temporisation (L7/L4)

Connect timeout - Établissement d'une connexion TCP/TLS.
TLS/Handshake timeout est une poignée de main TLS/HTTP2 preface.
Write timeout - Envoie une requête (y compris le corps).
Read timeout est l'attente du premier octet de réponse et/ou du corps entier.
Idle/Keep-Alive timeout est une connexion inactive.
Overall deadline est un délai « dur » pour l'ensemble de la demande (end-to-end).

2. 2 Budget du Taimaut (deadline budget)

Nous distinguons la cible 'deadline _ total' et divisons par étapes :
  • `ingress (gateway) + authZ + app + DB/cache + outbound PSP`.
Exemple pour payments 'POST' (cible 400 ms) :
  • passerelle : 30 ms,
  • annexe : 120 ms,
  • OBD : 120 ms,
  • PSP : 100 ms,
  • réserve : 30 ms.

2. 3 Propagation et annulation

« deadline »/« timeout » doit être transmis en bas de la chaîne (contexte, en-têtes, gRPC Deadline). À l'expiration, annuler les opérations en arrière-plan (abort/ctx cancel), nettoyer les verrous/sémaphores.


3) Stratégies d'installation des timeouts

1. Top-Down : Basé sur SLO et p95 - définir la fin-à-fin deadline, puis décomposer en sous-temps.
2. Identifiez les chemins « chers » (téléchargement de fichiers, rapports, PSP externes) - séparés plus longs mais limités.

3. Idempotent vs write:
  • idempotent (GET/répétitions de statut) - bref, plus agressif ;
  • write/money - un peu plus long, mais avec une répétition et une idempotence.
  • 4. Graduer par plans/tenants (l'entreprise peut avoir plus de timeout, mais moins de parallélisme).


4) Circuit breaker : modèles et paramètres

4. 1 Stratégies de déclenchement

Taux d'échec : Proportion d'erreurs ≥ X % sur la fenêtre N requêtes/heure.
Failures consultatives : M échecs consécutifs.
Slow-call rate : la proportion d'appels est plus longue que le seuil T.
Error classes : Les délais/5xx/connection-reset → « fatal », 4xx - ne sont pas pris en compte.

4. 2 états

Closed - rate tout, accumule les statistiques.
Open - panne instantanée (économise les ressources, ne pressent pas la dépendance).
Half-open - petits « échantillons » (N demandes) pour la « vérification de l'eau ».

4. 3 suppléments utiles

Bulkhead (cadres) : un pool de flux/connexions par dépendance pour que l'on ne « suce » pas tout.
Concurrence adaptative : limitation automatique du parallélisme (algorithmes AIMD/Vegas) par latence observée.
Load Shedding : défaillance/dégradation précoce en cas de pénurie de ressources locales (files d'attente, CPU, pauses GC).


5) Interaction : Délais, retraits, limites

D'abord la deadline, puis les retraits : chaque répétition doit être placée dans la deadline commune.
Backoff + jitter pour les répétitions ; respecter « Retry-After » et retry-budget.
Limite de taux : avec un breaker ouvert - abaissez les limites pour ne pas amplifier la tempête.
Idempotency : obligatoire sur les opérations de write (pour éviter les prises dans les temps « muets »).
Où rétracter : de préférence au bord (client/passerelle) plutôt qu'au fond.


6) Valeurs cibles pratiques (repères)

API de lecture publique : end-to-end '200-500 ms', read timeout '100-300 ms'.
Write critique (paiements) : '300-800 ms'e2e ; PSP externe ≤ '250-400 ms'.
Connect/TLS : "50-150 ms' (plus - problème de réseau/résolving).
Idle : « 30-90 s » (clients mobiles - bref pour économiser la batterie).
Ajustez les valeurs selon p95/p99 et les régions.


7) Configis et exemples

7. 1 Envoy (cluster + route, pseudo)

yaml clusters:
- name: payments_psp connect_timeout: 100ms type: STRICT_DNS lb_policy: ROUND_ROBIN circuit_breakers:
thresholds:
- priority: DEFAULT max_connections: 2000 max_requests: 2000 max_retries: 50 outlier_detection:
consecutive_5xx: 5 interval: 5s base_ejection_time: 30s max_ejection_percent: 50

routes:
- match: { prefix: "/api/v1/payments" }
route:
cluster: payments_psp timeout: 350ms        # per-request deadline idle_timeout: 30s retry_policy:
retry_on: "reset,connect-failure,refused-stream,5xx,gateways"
num_retries: 1 per_try_timeout: 200ms

7. 2 NGINX (périmètre)

nginx proxy_connect_timeout 100ms;
proxy_send_timeout  200ms;  # write proxy_read_timeout  300ms;  # read (первый байт/все тело)
keepalive_timeout   30s;
send_timeout     15s;

Быстрый отказ при перегрузке limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 50;

7. 3 gRPC (client, Go-pseudo)

go ctx, cancel:= context.WithTimeout(context.Background(), 350time.Millisecond)
defer cancel()
resp, err:= client.Pay(ctx, req) // Deadline передается вниз

7. 4 client HTTP (Go)

go client:= &http.Client{
Timeout: 350 time.Millisecond, // общий дедлайн на запрос
Transport: &http.Transport{
TLSHandshakeTimeout: 100 time.Millisecond,
ResponseHeaderTimeout: 250 time.Millisecond,
IdleConnTimeout: 30 time.Second,
MaxIdleConnsPerHost: 100,
},
}

7. 5 Resilience4j (Java, pseudo)

yaml resilience4j.circuitbreaker.instances.psp:
slidingWindowType: TIME_BASED slidingWindowSize: 60 failureRateThreshold: 50 slowCallDurationThreshold: 200ms slowCallRateThreshold: 30 permittedNumberOfCallsInHalfOpenState: 5 waitDurationInOpenState: 30s

resilience4j.timelimiter.instances.psp:
timeoutDuration: 350ms

8) Observabilité et alerties

8. 1 Métriques

`http_client_requests{endpoint, status}`, `client_latency_bucket`

`timeouts_total{stage=connectreadwritedeadline}`
`circuit_state{dependency}`: 0/1/2 (closed/half/open)
`slow_call_rate`, `failure_rate`
`active_concurrency{route, dependency}`
`shed_requests_total{reason}` (load shedding)
`retry_total{reason}`, `retry_budget_used`

8. 2 Tracs

Spans : ingress → handler → DB/Redis → externe.
Attributs : 'timeout _ ms _ target', 'circuit _ state', 'queue _ time _ ms'.
Exemplars : lier les piques p99 à des traces-id spécifiques.

8. 3 Alert

'p99 _ latency {critical}> cibles X minutes consécutives.
'timeout _ rate {dependency}' saut> Y %.
Transitions fréquentes vers 'open '/' flapping' breaker.
Croissance 'shed _ requests _ total' à CPU/GC élevé.


9) Adaptive Concurrency & Load Shedding

9. 1 Idée

L'automatisation réduit le parallélisme lors de la croissance des queues de latence :
  • AIMD : augmenter lentement, réduire brusquement.
  • Vegas-like : garder la file d'attente cible (queue time).
  • Token-based : chaque demande « brûle » un token ; les jetons sont émis à la vitesse mesurée.

9. 2 Réalisation

Sémaphores locaux par route ; le but est de maintenir 'queue _ time' en dessous du seuil.
Un « fusible » global (limite RPS/concurrence) sur la passerelle.
En cas de pénurie de CPU/connexions, une défaillance précoce avant l'exécution de la logique (429/503 avec « Retry-After »).


10) Tests et scénarios de chaos

Injection de latitude : ajouter artificiellement 50-300 ms par dépendance.
Packet loss/dup/drop (tc/tbf, Toxiproxy).
Knob turning : réduire les pools de connexion, augmenter la charge de travail jusqu'à la saturation.
Kill/Degrade une zone/shard (indisponibilité partielle).
Contrôles : si la tempête rétrospective n'échoue pas ; le breaker s'ouvre de manière prévisible ; N'est-ce pas que la file augmente.


11) Anti-modèles

Un seul « read timeout » global sans détail connect/TLS/per-etage.
L'absence de dédain commun → de rétractation va au-delà du SLO.
Retrai sans jitter et sans retry-budget.
Connexions « éternelles » sans idle-timout → fuite de descripteurs.
Breaker considère le 4xx comme une erreur fatale.
Pas d'annulation/abort → les travaux de fond continuent après le délai d'attente du client.
Délais trop longs pour les réseaux mobiles/instables.


12) Spécificité de l'iGaming/Finance

Write critique (dépôts/conclusions) : Une courte répétition avec Idempotency-Key, puis "202 Accepted' + polling au lieu d'attentes infinies.
PSP/services bancaires : politiques séparées par fournisseur/région (certaines plus lentes).
Paiements responsables et limites : en cas de blocage/revue - rapide '423/409', ne pas étirer les opérations « suspendues ».
Reporting/agrégation : Exécute asynchrone (batch + ressource d'état).


13) Chèque-liste prod-prêt

  • Défini comme étant la fin de la fin de la vie sur les itinéraires critiques (GET/POST).
  • Le budget est décomposé en étapes ; propagation debline incluse.
  • Configurations connect/TLS/read/write/idle timeouts sur la passerelle et les clients.
  • Circuit breaker avec des seuils de taux d'échec et de slow-call ; logique half-open correcte.
  • Bulkheads sur les dépendances ; limites du parallélisme par route.
  • Load shedding avant d'exécuter la logique d'entreprise en cas de surcharge.
  • Intégration avec les retraits : backoff + gitter, retry-budget, respect de « Retry-After ».
  • Idempotence write, 'Idempotency-Key' et outbox pour les événements.
  • Métriques : timeout/slow-call/état breaker/queue time/concurrence.
  • Tests de chaos : injection de retards/pertes/défaillances, dégradation des zones.
  • Documentation pour les clients : exemples de timing, codes de réponse, conseils de répétition.

14) TL; DR

Donnez à chaque demande une deadline rigide, répartissez-la en étapes et distribuez-la en bas de la chaîne. Gérer les pannes via circuit breaker + bulkheads + concurrence adaptive + load shedding. Répétitions - seulement dans le cadre de la date limite, avec un gitter et un budget ; write - idempotent seulement. Mesurer timeout/slow-call, état breaker et 'queue _ time', courir régulièrement des tests de chaos.

Contact

Prendre contact

Contactez-nous pour toute question ou demande d’assistance.Nous sommes toujours prêts à vous aider !

Commencer l’intégration

L’Email est obligatoire. Telegram ou WhatsApp — optionnels.

Votre nom optionnel
Email optionnel
Objet optionnel
Message optionnel
Telegram optionnel
@
Si vous indiquez Telegram — nous vous répondrons aussi là-bas.
WhatsApp optionnel
Format : +code pays et numéro (ex. +33XXXXXXXXX).

En cliquant sur ce bouton, vous acceptez le traitement de vos données.