DEV Community

Gabriel Moreira
Gabriel Moreira

Posted on

# Sobrevivendo ao Caos: Quebrando Coisas de Propósito com o ChaosEngineeringMasterDeck

Introdução ao Chaos Engineering

Chaos Engineering é a prática de injetar falhas controladas em um sistema para descobrir seus pontos fracos antes que um incidente real aconteça.

Por que quebrar coisas de propósito? Porque em sistemas distribuídos falhar é normal. É melhor descobrir um problema numa terça de manhã, com o time preparado, do que numa sexta à noite com o cliente reclamando.

A mudança de mentalidade é simples:

  • Antes: "Vamos evitar que o sistema falhe."
  • Agora: "O sistema vai falhar. Vamos garantir que ele aguente."

Conceitos-chave:

  • Estado estável: o comportamento normal do sistema, medido por métricas (ex.: taxa de erro, latência).
  • Blast radius: o tamanho máximo do estrago que aceitamos causar no experimento.
  • Observabilidade: logs, métricas e traces para enxergar o que está acontecendo.

Dissecando o ChaosEngineeringMasterDeck

O ChaosEngineeringMasterDeck é um baralho de cartas de experimento. Cada carta descreve uma falha para testar, de forma padronizada. Nas nossas Game Days, sorteamos uma carta e executamos o experimento.

Toda carta tem:

  1. Hipótese: o que esperamos que aconteça.
  2. Variável: a falha que vamos injetar.
  3. Métricas de controle: como saber se o sistema continua saudável.
  4. Blast radius: o limite do impacto.
  5. Condição de aborto: quando parar tudo.

Exemplo de carta:

id: CARD-014
nome: "A Lentidão Silenciosa"
hipotese: "Com +2s de latência no payment-service, o checkout continua >= 95%."
variavel: latencia de 2000ms em 25% das requisicoes
metricas: [taxa_checkout_concluido, latencia_p99, taxa_erro_5xx]
blast_radius: "1 pod, 5% do trafego, 10 minutos"
aborto: "checkout < 90% por 60s"
Enter fullscreen mode Exit fullscreen mode

Estudo de Caso: A Lentidão Silenciosa

Arquitetura: e-commerce na AWS, com microsserviços em Spring Boot rodando no EKS. O checkout-service chama o payment-service, e usa Resilience4j para resiliência.

Carta sorteada: CARD-014, que simula alta latência no serviço de pagamento.

Blast radius:

  • Apenas 1 pod do payment-service
  • Cerca de 5% do tráfego
  • Duração máxima de 10 minutos
  • Primeiro em staging, depois em produção-canário

Hipótese: o Circuit Breaker vai abrir e o fallback vai enfileirar os pagamentos, mantendo o checkout acima de 95%.

Trecho do fallback testado:

@CircuitBreaker(name = "paymentService", fallbackMethod = "pagarAsync")
public PedidoResultado finalizarPedido(Pedido pedido) {
    return paymentClient.cobrar(pedido);
}

private PedidoResultado pagarAsync(Pedido pedido, Throwable ex) {
    paymentQueue.enfileirar(pedido); 
    return PedidoResultado.pendentePagamento(pedido.getId());
}
Enter fullscreen mode Exit fullscreen mode

Observabilidade e Resultados

Monitoramos tudo com Prometheus + Grafana (métricas) e Jaeger (traces).

O que aconteceu:

  • O Circuit Breaker abriu depois de cerca de 80 segundos.
  • O fallback assumiu e o checkout ficou em 97%.
  • O alerta de latência disparou como esperado.

A arquitetura sobreviveu? Sim, com ressalvas. O experimento mostrou problemas:

  • O Circuit Breaker demorou demais para abrir (janela grande).
  • O Retry dobrou a carga no serviço lento.
  • O Auto Scaling não reagiu, porque olhava só a CPU e não a latência.

Padrões em ação: Circuit Breaker, Fallback e Timeout funcionaram. Retry e Auto Scaling precisaram de ajuste.

Conclusão

Lições aprendidas:

  1. Resiliência é uma hipótese: só se confirma testando.
  2. Configurações padrão precisam ser calibradas.
  3. Comece pequeno: blast radius reduzido, risco reduzido.
  4. Sem observabilidade, não existe experimento.

Na cultura DevOps, o ganho maior foi mudar a postura do time: falhas deixam de ser motivo de culpa e viram oportunidade de aprendizado. Descobrir um problema num experimento planejado é muito melhor do que descobrir num incidente real.

Top comments (0)