GH GambleHub

Timeout и circuit control

1) Por que é necessário

Os sistemas não caem de uma falha fatal, mas sim de uma acumulação de atrasos e retalhos de ondas. Os temporizadores limitam o tempo de espera e liberam recursos, e o circuito de controle (breaker + shedding + competição adaptativa) impede a degradação da cadeia de dependências. O objetivo é manter o p95/p99 nos limites de destino e manter a disponibilidade em casos de falhas parciais.


2) Definições básicas

2. 1 Tipos de temporizadores (L7/L4)

Connect timeout - Estabelecendo uma conexão TCP/TLS.
TLS/Handshake timeout - apertos de mão TLS/HTTP2 preface.
Write timeout - enviar uma consulta (incluindo o corpo).
Read timeout - esperando o primeiro byte de resposta e/ou todo o corpo.
Idle/Keep-Alive timeout é uma conexão inativa.
Overall deadline - prazo «rígido» para todo o pedido (end-to-end).

2. 2 Orçamento de timeout (deadline boodget)

Destacamos o alvo 'deadline _ total' e dividimos por estágios:
  • `ingress (gateway) + authZ + app + DB/cache + outbound PSP`.
Exemplo para payments 'POST' (alvo 400 ms):
  • gateway: 30 ms,
  • aplicação: 120 ms,
  • BD: 120 ms,
  • PSP: 100 ms,
  • Reserva: 30 mc.

2. 3 Propagation e cancelamento

'deadline '/' timeout' deve ser transmitido para baixo na cadeia (contexto, títulos, gRPC Deadline). Ao terminar, cancelar as operações de fundo (abort/ctx cancel), limpar bloqueios/semafores.


3) Estratégias de instalação de temporizadores

1. De cima para baixo: com base em SLO e p95 - definir end-to-end deadline, então dividir em debaixo de tempo.
2. Identificar caminhos «caros» (download de arquivo, relatórios, PSP externos) - individualmente longos, mas limitados.

3. Idempotent vs write:
  • idempotent (GET/repetições de status) - mais curto, mais agressivo;
  • write/dinheiro - um pouco mais longo, mas com uma única vez de repetição e idimpotência.
  • 4. Gradual em planos/tenantes (enterprise pode ter timeout mais longo, mas menos paralelismo).


4) Circuito breaker: modelos e parâmetros

4. 1 Políticas de execução

Failure-rate: taxa de erro ≥ X% na janela N/hora.
Consectiva failures: M fracassos consecutivos.
Slow-call rate: proporção de chamadas acima do limite T.
Error classes: temporizações/5xx/connation-reset → «fatais», 4xx - não levamos em conta.

4. 2 Estados

Closed - omite tudo, acumula estatísticas.
Open é uma falha instantânea (economiza recursos, não pressiona dependência).
Half-open - pequenas «amostras» (N) para «verificação de água».

4. 3 Adições úteis

Bolkhead (espigões): um pool de fluxo/conexões de dependência para que um não «suge» tudo.
Adaptável concurrency: limitação automática do paralelismo (AIMD/Vegas-algoritmos similares) por latência observada.
Load Shedding: falha precoce/degradação com falta de recursos locais (filas, CPU, pares GC).


5) Interação: temporizadores, retais, limites

Primeiro o deadline, depois o retrai, cada repetição tem de ser feita em um deadline comum.
Backoff + jitter para repetições; respeitar 'Retry-After' e retry-boodget.
Rate limiting: com breaker aberto - reduza os limites para não aumentar a tempestade.
Idempotency: obrigatória em operações write (para evitar duplicações em temporais mudos).
Onde retrabalhar: Preferencialmente na borda (cliente/gateway) do que no fundo.


6) Metas práticas (indicações)

Read API público: end-to-end '200-500 ms', read timeout '100-300 ms'.
Criticas write (pagamentos): '300-800 ms' e2e; PSP externo ≤ '250-400 ms'.
Connect/TLS: '50-150 ms' (mais: problema de rede/solução).
Idle: '30-90 c' (clientes móveis - mais curtos para economizar bateria).
Ajuste os valores por p95/p99 e regiões.


7) Configs e exemplos

7. 1 Envoy (cluster + rota, 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 (perímetro)

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 (cliente, Go-pseudo)

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

7. 4 cliente 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) Observabilidade e alertings

8. 1 Métricas

`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 Trailers

Spans: ingress → handler → DB/Redis → externos.
Atributos: 'timeout _ ms _ target', 'circuito _ state', 'queue _ time _ ms'.
Exemplares: vincular p99 picos a um trace-id específico.

8. 3 Alertas

'p99 _ latency <critical a.'> alvos X minutos seguidos.
'timeout _ rate <dependency 03' é saltado> Y%.
Transições frequentes para 'open '/' flapping' breaker.
Altura de 'shed _ requests _ total' com alta CPU/GC.


9) Adaptive Concurrency & Load Shedding

9. 1 Ideia

A automação reduz o paralelismo quando as caudas de latência crescem:
  • AIMD: Aumentar lentamente, reduzir drasticamente.
  • Vegas-semelhante: mantenha a fila de destino (queue time).
  • Token-based: Cada pedido «queima» o token; os tokens são emitidos a uma velocidade medida.

9. 2 Implementação

Semaforas locais per-road; o objetivo é manter 'queue _ time' abaixo do limite.
O «fusível» global (RPS/Concorrência Limite) na entrada.
Quando há falta de CPU/conexões, falha precoce antes da lógica (429/503 com 'Retry-After').


10) Testes e cenários de caos

Latency inhation: adicionar artificialmente 50-300 ms ao vício.
Packet loss/dup/drop (tc/tbf, Toxiproxy).
Knob turning: reduzir pool de conexões, aumentar a carga para saturação.
Kill/Degrade uma zona/shard (indisponibilidade parcial).
Verificações: Não «falha» se a tempestade retrai; breaker abre previsivelmente; A fila não cresce.


11) Antipattern

Um «read timeout» global sem detalhar connect/TLS/para-estágio.
A falta de um dedline comum → retais vão além do SLO.
Retrai sem jitter e sem retry-boodget.
Ligações «eternas» sem idle-temporizadores → fuga de descriptor.
Breaker considera o 4xx como erros fatais.
Sem cancelamento/abort → os trabalhos de fundo continuam após o tempo de espera do cliente.
Tempo muito longo para redes móveis/instáveis.


12) Especificidades do iGaming/Finanças

Write crítico (depósitos/conclusões): uma breve repetição com Idempotency-Key, seguida por '202 Accepted' + polling em vez de expectativas infinitas.
PSP/banking: políticas separadas de provedor/região (algumas mais lentas).
Pagamentos responsáveis e limites: com bloqueio/revezamento, rápido '423/409', sem esticar transações pendentes.
Relatórios/agregações - execute asincronicamente (batch + status-recurso).


13) Folha de cheque pró-prontidão

  • Definido end-to-end deadline através de rotas críticas (GET/POST).
  • O orçamento por estágio está decomposto; A propagation deadline está ativada.
  • Configh connect/TLS/read/write/idle temporizações na entrada e clientes.
  • Circuito breaker com liminares failure-rate e slow-call; uma lógica half-open correta.
  • Bolkheads dependentes; limites de paralelismo per-road.
  • Load shedding antes de executar a lógica empresarial quando sobrecarregada.
  • Integração com retrações: backoff + jitter, retry-boodget, respeito 'Retry-After'.
  • Idempotidade write, 'Idempotency-Key' e outbox para eventos.
  • Métricas: timeout/slow-call/status breaker/queue time/competição.
  • Testes de caos: injeção de atrasos/perdas/falhas, degradação de zonas.
  • Documentação para clientes: exemplos de temporizações, códigos de resposta, dicas de repetição.

14) TL; DR

Deadline rígido a cada pedido, espalhe-o em estágios e espalhe-o para baixo na cadeia. Gerencie as falhas através do circuito breaker + bulkheads + adaptativa concurrency + load shedding. Repetições - apenas dentro do deadline, com jitter e orçamento; write - apenas idimpotentes. Mede timeout/slow-call, estado breaker e 'queue _ time', faça testes regulares de caos.

Contact

Entrar em contacto

Contacte-nos para qualquer questão ou necessidade de apoio.Estamos sempre prontos para ajudar!

Iniciar integração

O Email é obrigatório. Telegram ou WhatsApp — opcionais.

O seu nome opcional
Email opcional
Assunto opcional
Mensagem opcional
Telegram opcional
@
Se indicar Telegram — responderemos também por lá.
WhatsApp opcional
Formato: +indicativo e número (ex.: +351XXXXXXXXX).

Ao clicar, concorda com o tratamento dos seus dados.