DEV Community

Sobrevivendo ao Caos: Injetando Falhas Estratégicas com o ChaosEngineeringMasterDeck

Se você trabalha com sistemas distribuídos e arquitetura em nuvem, já deve ter se deparado com as falácias da computação distribuída. A rede não é confiável, a latência não é zero e a topologia muda constantemente. Servidores caem, zonas de disponibilidade (AZs) inteiras sofrem instabilidade e bancos de dados entram em deadlock.

Historicamente, a engenharia de software tentou construir sistemas perfeitos onde a falha era tratada como uma anomalia inadmissível. Hoje, a abordagem arquitetural mais madura é exatamente o oposto: nós abraçamos a falha. Desenvolvemos com a premissa de que a degradação de componentes é inevitável. É aqui que entra o Chaos Engineering.

Neste artigo, vou compartilhar como elevamos a barra de resiliência utilizando o ChaosEngineeringMasterDeck, uma ferramenta estratégica que nos permitiu transformar a resposta a incidentes de uma reação baseada em pânico para um processo validado e científico.

A Ciência do Chaos Engineering

O Chaos Engineering não é simplesmente "quebrar coisas de propósito" em produção de forma anárquica. Segundo o manifesto oficial (Principles of Chaos Engineering), trata-se da disciplina de realizar experimentos em um sistema distribuído para construir confiança na sua capacidade de suportar condições turbulentas.

A mudança de mentalidade (Shift-Left Reliability) é profunda:

  • Antes: O foco era estritamente em MTBF (Mean Time Between Failures) – tentar ao máximo evitar que a falha ocorra.
  • Depois: O foco muda para MTTR (Mean Time To Recovery) e resiliência ativa. "Vamos injetar latência no serviço de pagamentos hoje, em um ambiente controlado, para provar que nossa arquitetura de fallback e desbalanceamento de carga reage corretamente antes do pico da Black Friday."

Dissecando o ChaosEngineeringMasterDeck

Para trazer essa cultura para o nosso dia a dia de forma rigorosa, adotamos o ChaosEngineeringMasterDeck. O Master Deck atua como um framework de experimentação gamificado, estruturado em formato de "cartas" ou cenários catalogados. Cada cenário modela um vetor de falha específico que pode atingir nossa arquitetura.

Quando "puxamos uma carta" durante nossos Game Days, seguimos um rigoroso método científico:

  • Estado Estável (Steady State): Definição de como o sistema se comporta quando está saudável, baseado em métricas de negócio e de sistema. (Ex: 99% das requisições de checkout respondidas em menos de 200ms com taxa de erro menor que 0,1%).
  • Hipótese: Uma premissa testável. "Se o microsserviço de Pagamentos sofrer degradação de rede, o serviço de Checkout deve abrir o Circuit Breaker, retornar dados em cache ou aceitar o pedido de forma assíncrona, sem gerar indisponibilidade (erro 500) para o usuário final."
  • Variáveis de Injeção: O vetor de ataque. (Ex: Injetar 5 segundos de latência e 30% de perda de pacotes via AWS FIS ou Chaos Mesh).
  • Métricas de Controle (Observabilidade): Quais dashboards (Grafana, Datadog) e métricas RED (Rate, Errors, Duration) provarão ou refutarão a hipótese.
  • Plano de Abortar (Rollback): O "botão de pânico". Condições exatas sob as quais o experimento deve ser interrompido para não impactar os SLAs do negócio.

Estudo de Caso Profundo: A Carta do "Tarpit de Latência"

Em nossa última simulação, executamos a carta Tarpit de Latência. O objetivo era validar os mecanismos de proteção do nosso core de transações contra serviços de terceiros lentos – um cenário especialmente problemático em Node.js, devido à sua natureza single-threaded, em que conexões presas podem esgotar o pool de recursos rapidamente.

O Cenário Arquitetural

Nossa arquitetura conta com um Microsserviço de Checkout (desenvolvido em Node.js com TypeScript e Arquitetura Limpa), que se comunica via HTTP com o Microsserviço de Pagamentos, responsável por repassar a transação a um Gateway externo.

  • A Falha Injetada: Adicionamos 5 segundos de latência em 50% das chamadas de rede que saíam do microsserviço de Checkout para o de Pagamentos.
  • O Blast Radius (Raio de Explosão): Para mitigar riscos reais, aplicamos o conceito de Blast Radius contido. O experimento rodou no ambiente de Produção, mas limitamos o tráfego afetado exclusivamente a contas de usuários BETA internos usando um sistema de Feature Flags.

A Resposta do Sistema e Padrões Aplicados

Assim que a latência foi injetada, a degradação começou, e a observabilidade entrou em cena. O que ocorreu sob o capô?

  • Detecção via Métricas RED: O monitoramento capturou imediatamente o aumento na Duração (Duration) das requisições. O tracing distribuído (OpenTelemetry) mostrou os spans parados na borda da rede.
  • Abertura do Circuit Breaker: Utilizamos a biblioteca Opossum no Node.js para implementar o padrão Circuit Breaker. Ao perceber que o limite de timeouts falhos ultrapassou o threshold (ex: 50% de falhas em 10 segundos), o circuito transitou do estado CLOSED para OPEN.
  • Fail-Fast e Prevenção de Cascata: Com o circuito OPEN, o microsserviço de Checkout parou instantaneamente de enviar novas requisições para a rede. Em vez de esperar 5 segundos e travar a Event Loop do Node.js, ele começou a falhar rápido (Fail-Fast), liberando recursos computacionais e prevenindo um colapso em cascata.
  • Fallback e Consistência Eventual: A requisição não foi perdida. A rota de fallback foi ativada. O sistema sacrificou a consistência imediata pela disponibilidade (princípio do Teorema CAP): o pedido foi aceito com status "Pendente", o usuário recebeu a mensagem "Estamos processando seu pagamento em segundo plano", e o payload foi publicado em uma fila do RabbitMQ/Kafka para processamento assíncrono (Dead Letter e Retry automatizado) assim que o circuito voltasse ao estado HALF-OPEN e posteriormente CLOSED.

Conclusão e Trade-offs Arquiteturais

A adoção do ChaosEngineeringMasterDeck provou que resiliência não é algo que você adiciona no final do projeto; é um requisito não funcional que dita o design da arquitetura (Shift-Left).

  • Assumir Trade-offs: Aprendemos a escolher conscientemente entre consistência e disponibilidade. Proteger a Event Loop em sistemas Node.js exigiu desacoplamento com mensageria.
  • Segurança Psicológica: A equipe desenvolve e faz deploys com mais confiança, sabendo que os padrões de tolerância a falhas são postos à prova constantemente.
  • Observabilidade como Alicerce: Testar falhas às cegas é inútil. Sem logs estruturados, tracing e métricas acionáveis, o caos é apenas destruição.

Ao abraçar o caos, deixamos de ser reféns da instabilidade da rede e passamos a dominar a estabilidade das nossas aplicações.

Fontes e Referências

Top comments (0)