Integração e API
Circuit Breaker
O circuito abre quando um contador, taxa ou janela de falhas ultrapassa o limiar; enquanto aberto, novas chamadas falham rapidamente. Após 30 s, por exemplo, passa a half-open e libera testes limitados. O padrão Circuit Breaker difere de retry: ele impede tentativas prováveis de falhar. Microsoft Azure e bibliotecas como Polly documentam a combinação. A implantação exige métricas por dependência e operação; um limiar global pode bloquear funções saudáveis e esconder falhas.
🔀 Tipos de Comunicação
CLOSED
Estado fechado
No estado fechado, as chamadas passam. O breaker observa resultado e latência. Falhas são classificadas. Timeout, conexão recusada, 502, 503 e 504 podem contar. Erros 400 por pedido inválido normalmente não. 401 pode indicar credencial e exigir abrir até correção, mas a política depende. A janela pode ser de últimas 100 chamadas ou 30 s. Um limiar de 50% só faz sentido com volume mínimo; 1 falha em 1 chamada não deveria necessariamente abrir. O breaker registra sucessos. Após estabilidade, contadores deslizam. A instrumentação precisa ter tags com baixa cardinalidade: serviço, operação e região. Não usar device_id de milhões como label em métrica.
OPEN
Estado aberto
Ao atingir a condição, o breaker abre e rejeita imediatamente. A resposta pode usar erro interno, 503 ou fallback. O objetivo é não consumir threads e conexões aguardando uma dependência que falha. Isso protege o chamador e dá tempo ao serviço. O período, como 30 s, precisa ser maior que ruído e menor que indisponibilidade tolerada. Um open muito curto cria rajadas de teste. Muito longo prolonga falha após recuperação. Durante aberto, métricas e alerta continuam. O sistema não deve mascarar como sucesso se a ação é crítica. Um dashboard pode mostrar cache; uma fechadura não deve fingir que destravou. Fallback precisa ser semanticamente seguro.
HALF-OPEN
Estado half-open
Depois do tempo aberto, o breaker permite uma quantidade limitada de chamadas de prova. Uma ou algumas passam. Se têm sucesso, fecha; se falham, reabre. Liberar todas cria avalanche. Em cluster, o estado pode ser por instância ou compartilhado. Por instância distribui testes, mas várias podem atingir o serviço. Compartilhado coordena, mas adiciona dependência. A escolha depende da escala. Jitter no tempo reduz sincronização. O teste deve ser representativo. Um health endpoint pode responder 200 enquanto a operação real falha; usar chamada real controlada é melhor. Operações com efeito precisam de idempotência. A prova não deve duplicar comando.
SLO
Breaker adaptativo por latência e taxa
Além de erros, latência acima do orçamento pode contar como falha lenta. Se 80% das chamadas passam, mas levam 20 s, o sistema já está degradado. Time limiter e breaker trabalham juntos. Algoritmos usam janela deslizante e taxa de chamadas lentas. Resilience4j oferece parâmetros. Envoy e service meshes implementam outlier detection e circuit breaking em outro nível. O breaker de aplicação conhece semântica; o proxy conhece conexão. Ambos podem coexistir. Configurações conflitantes dificultam. O projeto deve ter uma política principal e observar. Limites são ajustados por dados de produção, não copiados.
✅ Vantagens Arquiteturais
⚡
Evita cascata de timeouts e esgotamento de recursos
Sem breaker, 100 threads podem esperar 30 s por uma API caída. Novas requisições entram, filas crescem e o serviço local falha. Ao abrir, chamadas retornam em milissegundos. CPU e conexões ficam disponíveis. Isso é vital em automação: uma nuvem de clima indisponível não deveria impedir luz local. A arquitetura separa dependências. O breaker deve ser por serviço e operação. Se uma única função falha, não abrir tudo. O isolamento também usa pools separados, bulkhead e limites. Breaker sozinho não impede que uma operação lenta consuma antes de abrir; timeout é obrigatório.
⚡
Reduz pressão sobre a dependência durante recuperação
Repetições agressivas podem manter um serviço sobrecarregado. O open corta. Half-open testa. Com retry, a ordem importa: normalmente poucas retentativas com backoff ocorrem dentro da chamada, e o breaker observa o resultado agregado, ou vice-versa conforme biblioteca. Uma política mal composta multiplica chamadas. Três retries em duas camadas geram nove. O sistema precisa contar. O breaker não substitui rate limit. Ele responde a falha; rate limit controla carga. Quando o problema é quota 429, respeitar `Retry-After` pode ser melhor. Classificação de erro define.
⚡
Permite degradação controlada em vez de falha total
Se previsão meteorológica falha, a irrigação pode usar última leitura com idade e limite, ou adiar. Se cloud de lâmpada falha, o app mostra offline e controles locais permanecem. O fallback precisa declarar stale. Não usar dado antigo sem timestamp. Em segurança, fail-safe é específico: uma porta não destrava por ausência de serviço; uma saída de emergência tem lógica própria. O breaker ativa fallback, mas não decide. Cada caso precisa de análise. A experiência do morador melhora porque a interface responde rápido e explica, em vez de girar por 30 s.
⚡
Gera sinal operacional claro de dependência degradada
Transições closed→open→half-open são eventos. Alertas podem ser baseados em tempo aberto e volume afetado. Métricas incluem estado, falhas, chamadas não permitidas e duração. Logs precisam evitar spam por cada chamada rejeitada; agregam. Um breaker abrindo frequentemente indica serviço instável, timeout curto ou limiar errado. O dashboard mostra. Tracing registra `circuit_open`. Essa observabilidade reduz MTTR. O breaker não corrige. Equipes precisam investigar DNS, certificado, quota, API, rede ou carga. Configuração automática sem revisão pode esconder meses.
⚡
Torna política de resiliência reutilizável
Bibliotecas como Polly para .NET, Resilience4j para Java e resilience patterns em proxies oferecem. Uma política pode ser aplicada a clientes HTTP. O benefício é consistência. A política deve permitir ajustes por dependência. Um sensor local com resposta em 100 ms e uma cloud com 5 s não usam o mesmo timeout. O código de negócio recebe erros tipados. A configuração fica versionada. Testes simulam. Um breaker é um padrão, não um produto. Usar biblioteca não elimina entender estados e composição. Defaults raramente são adequados a todas as operações.