Circuito Breaker e degradação
O Circuito Breaker (CB) é um pattern de proteção que interrompe chamadas para dependência degradada para localizar a falha e proteger os serviços de upstream e o usuário. Degradação (graceful degradation) - Simplificação consciente da funcionalidade em casos de falta de recursos ou falhas (por exemplo, retorno de dados em dinheiro/incompletos, desativação de fichas «caras») sem downtime completo.
O objetivo principal é manter o SLO e a experiência do usuário através de falhas controladas, em vez de baixas em cascata.
1) Quando aplicar
A dependência é instável: p95/p99, temporizações, respostas erradas.
API externa com limites rígidos/penalti.
Backends «pesados» (buscas, recomendações, relatórios) onde os retais aumentam a tempestade.
Áreas altamente carregadas com risco de esgotamento de pool (compostos, trejeitos).
2) Estados CB e transições
Três clássicos:1. Closed - tráfego em andamento, métricas de erro/latência contam.
2. Open - as chamadas são rejeitadas instantaneamente (fail-fast) e/ou traduzidas para fallback.
3. Half-Open - Um número limitado de consultas de «teste» determina se o interruptor é fechado.
Desencadeadores de abertura
Limite de erros/temporizações por janela (por exemplo, ≥ 50% dos últimos N).
Limite de latência (p95> destino, por exemplo).
Políticas combinadas (erros ∧ tempo excedido).
Tempo de retenção (cool-down)
Fixo (por exemplo, 10-60 segundos) ou adaptativo (aumento exponencial em reativações).
3) Temporizadores, retais e jitter
Os horários são sempre mais curtos que o SLO upstream e alinhados em cadeia (deadline propagation).
Retraias apenas para operações idumpotentes; 1 ou 2 tentativas são suficientes na maioria das vezes.
Backoff + jitter (full jitter) impede ondas sincronizadas de repetição.
Hedging (pedidos de reposição) - Economizado e apenas para leituras muito críticas.
4) Bulkhead-isolamento e «fusíveis»
Divida os pools de conexões/corretores/filas de domínios e tipos de tráfego (VIP, tarefas de fundo, APIs públicas).
Caps em concurrency para operações «caras».
Controle de adesão: Falha fácil antes de a fila ficar cheia.
5) Fallback e cenários de degradação
Opções
«Stale-while-revalidate», devolve os dados de L2/L3 em dinheiro.
Read-only: bloco escrever/comandos, permitir leituras seguras.
Respostas de aluguel: dados incompletos (por exemplo, sem recomendações/avatares).
Desativação funcional: ocultar temporariamente widgets/fichas não críticos.
Função flags: mudança rápida de comportamento sem lançamento.
Regras
Fallback deve ser determinado, rápido e seguro de acordo com os dados.
Marquem claramente o caminho degradado em logs/trens/métricas.
6) Priorização e tráfego-shaping
Planos VIP/pagos - maior prioridade/quotas para o déficit.
Rate limits e throttling reduzem a pressão sobre dependências degradadas.
Shed load: redução suave da qualidade (por exemplo, menos resultados, imagens cortadas) antes da estabilização.
7) Observabilidade e sinalização
Métricas CB
Estado (closed/open/half-open) e duração em estado.
Taxa de rejeição por razões: CB-open, timeout, 5xx, retry-exhausted.
p95/p99 latência «antes» e «depois» do interruptor.
Cal-vo/fração de solicitações via fallback.
Training
Anotações de spans: 'circuito = opened', 'fallback = cachê', 'admissão = denied'.
Correlação com limites (429/RateLimit -), filas e balas de conexão.
Logs/auditoria
Razão para abrir/fechar, liminares, identificadores de dependência.
8) Contratos e protocolo
HTTP
Fast-fast: '503 Service Unavailable' s 'Retry-After' (ou '429' em limites).
Parcial conteúdo/estale: '200 '/' 206' com metadados de degradação (por exemplo, 'X-Degraded: true').
Políticas em dinheiro: 'Castelo-Controle: stale-if-erro, stale-while-revalidate'.
gRPC
'UNAVAILABLE', 'DEADLINE _ EXCEEDED', uma semântica de retais nas polícias do cliente/proxy.
Deadline/timeout no contexto da solicitação; Espalhar o deadline para baixo na cadeia.
Idempotidade
'Idempotency-Key' para operações POST, dedução na fronteira.
9) Implementação típica (pseudocode)
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)
Half-Open Amostra
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) Configuração de liminares
Janela de observação: deslizante N segundos/solicitações.
Limite de erro: 20% a 50% na janela (dependendo do perfil).
Limite de latência: p95 ≤ SLO alvo (por exemplo, 300-500 ms); excesso é contabilizado como «erro» para CB.
Hot-down adaptativo: 10s → 30s → 60s em reativações.
11) Testes e práticas de caos
Chaos: injeção de latência/erro dependendo, falha DNS, drop pacotes.
Game days: iniciar a «abertura» do interruptor em um ambiente de combate, verificar fallback.
Canary: inclua a política de degradação de ST primeiro para 1% a 5% do tráfego.
Orçamento SLO: admita experiências até esgotar o erro-budet.
12) Integração com multi-tenência
O estado CB pode ser armazenado per-dependency per-tenant (para locadores ruidosos) ou globalmente, dependendo do perfil de carga.
Dados Fallback e cachês segmentem por 'tenant _ id'.
Prioridades/quotas - de acordo com os planos (VIP não deve sofrer comportamento Starter).
13) Folha de cheque antes de vender
- Os temporizadores e deadline são passíveis e alinhados.
- Os retais são limitados, apenas para operações idumpotentes, com backoff + jitter.
- Os limites CB são justificados pelos dados do teste de carga.
- Caminhos Fallback existem, rápidos e seguros; O dinheiro da política está definido.
- Isolamento bulkhead: balas separadas/filas/limites.
- Métricas/trens/logs marcam a degradação e o estado de CB.
- Documentação dos contratos de resposta (HTTP/gRPC) com exemplos de títulos/códigos.
- Os cenários de caos e game-days são regulares; há um runbook.
14) Erros típicos
Não há temporizadores → retais e quedas em cascata.
Um CB global em vez de seletivo (por endpoint/método) é uma rejeição extra.
Disjuntor aberto sem fallback → telas «vazias» em vez de UX degradado.
Retraias sem jitter → tempestades sincronizadas de pedidos.
Duração durável em falhas de curto prazo ou demasiado curto em estados resistentes - flip-flop.
Falta de bolkhead - exaustão de pool compartilhado e «head-of-line blocking».
15) Escolha rápida de estratégia
Leituras de alta importância: CB + caixa de respostas stale + hedging (baixo custo).
Registros/pagamentos: tempo rigoroso, mínimo de retrações, idempotency keys, falta de fallback «sujo».
API externo: CB com liminares agressivos, hot-down adaptativo, throttling rigoroso.
Microsserviços com carga de pulso: bulkheads, caps em concurrency, priorização VIP.
Conclusão
O Circuito Breaker e a degradação controlada são o «seguro» da arquitetura, que traduz falhas caóticas em comportamento previsível. Temporizações claras, retais limitados com jitter, pulas isoladas, caminhos fallback elaborados e telemetria tornam o sistema resistente a falhas de dependência e mantêm o SLO até mesmo em períodos de pico e emergência.