DEV Community

Gustavo B. de Abreu
Gustavo B. de Abreu

Posted on

Sobrevivendo ao Inevitável: Engenharia do Caos na Prática com o ChaosEngineeringMasterDeck

Se você trabalha com arquiteturas modernas em nuvem e microsserviços, provavelmente já se deparou com a clássica citação de Werner Vogels, CTO da Amazon:

"Failures are a given and everything will eventually fail over time." (Falhas são inevitáveis e tudo falhará com o tempo).

Em sistemas distribuídos, isso não é apenas uma frase de efeito; é uma realidade técnica. Redes sofrem partições, zonas de disponibilidade passam por degradação, storages saturam, garbage collectors pausam execuções e bancos de dados encontram contenções de lock. Conforme os serviços se multiplicam em topologias complexas, o comportamento emergente dessas interações torna-se não linear e altamente imprevisível.

DIAGRAMA 1: Topologia de Microsserviços e Efeito Dominó em Sistemas Distribuídos


O Limite dos Testes Tradicionais

Historicamente, a engenharia de software concentrou seus esforços de qualidade em testes unitários, testes de integração e testes ponta a ponta. Embora indispensáveis, os testes tradicionais validam exclusivamente condições conhecidas — a essência da premissa assert(A == B) executada em um ambiente isolado e previsível.

O perigo em produção mora no desconhecido: o que acontece quando uma API externa não cai de vez (retornando um HTTP 500 rápido), mas começa a responder com latência intermitente de 900 ms e perda pontual de pacotes? Na ausência de isolamento, isso gera esgotamento de pools de threads, tempestades de retentativas (retry storms) e indisponibilidade generalizada.

É nesse cenário que a Engenharia do Caos (Chaos Engineering) atua:

"Chaos Engineering é a disciplina de experimentar sobre um sistema a fim de construir confiança em sua capacidade de resistir a condições turbulentas em produção." — Principles of Chaos Engineering.

Como sintetizou Nora Jones: "O caos não causa problemas. Ele os revela."

Mudar a mentalidade da equipe significa abandonar a busca utópica por sistemas invulneráveis e adotar a prática de projetar para degradação graciosa, failover testado e contenção ativa.


2. Dissecando o ChaosEngineeringMasterDeck

O ChaosEngineeringMasterDeck consolida os aprendizados desenvolvidos nos GameDays da Amazon e na experiência de resiliência da AWS e Netflix. No fluxo de trabalho do nosso projeto, o Master Deck atua como um catálogo operacional e framework para conduzir testes baseados no método científico.

DIAGRAMA 2: O Loop Científico do Caos - Steady State, Hipótese, Experimento, Verificação e Melhoria

As 5 Fases de Cada Experimento

  1. Estado Estável (Steady State): Definição do comportamento nominal do sistema orientada a métricas de negócio e experiência do usuário. O Master Deck reforça que métricas puramente computacionais (como CPU a 60%) não garantem que o usuário está sendo atendido. Mede-se o estado estável por indicadores como taxa de checkout por segundo (similar ao SPS da Netflix) ou latência percebida na borda.
  2. Hipótese (Hypothesis): Formulação técnica estruturada no formato "E se...?" (What if...?). Por exemplo: "Se o gateway de pagamentos atrasar 800 ms, o Circuit Breaker abrirá e as requisições serão degradadas graciosamente sem travar o pool de conexões". Princípio-chave: "Never assume. If you haven't verified it, it's probably broken."
  3. Execução (Run Experiment): Injeção da falha com escopo delimitado.
  4. Verificação (Verify): Avaliação precisa do impacto e dos tempos operacionais:
    • Time to Detect (Tempo de detecção);
    • Time to Graceful Degradation (Tempo de acionamento do fallback);
    • MTTR (Mean Time to Repair).

A disponibilidade de qualquer serviço é governada pela relação:

Disponibilidade = MTBF / (MTBF + MTTR)

Como falhas sempre ocorrerão em algum momento (desafiando o MTBF), a automação e o teste contínuo reduzem o MTTR para proteger o SLA.

  1. Melhoria (Improve): Condução de análise pós-incidente (Correction of Errors - COE) e implementação das correções de arquitetura.

Controles Críticos de Segurança

  • Blast Radius (Raio de Explosão) Controlado: Os testes começam na menor granularidade possível (instância única, tráfego canário ou staging espelhado) antes de expandir.
  • Emergency Stop (Botão de Aborto Imediato): Se as métricas vitais de negócio ultrapassarem o limiar tolerado de segurança, o experimento é interrompido instantaneamente.

3. Estudo de Caso Prático: Simulando Falha em Microsserviços

Para tangibilizar o processo, aplicamos as diretrizes do Master Deck a uma arquitetura distribuída de e-commerce e processamento de pedidos.

DIAGRAMA 3: Topologia da Arquitetura do Fluxo de Pedidos e Ponto de Injeção de Falha

A "Carta" de Caos Selecionada

  • Identificador da Instrução: DECK-NET-03: Latency & Packet Loss in Downstream Dependency.
  • Alvo: Rota de comunicação entre o microsserviço de pedidos (Order Service) e o proxy de integração com o gateway de pagamento externo.
  • Mecanismo de Injeção: Configuração do ToxiProxy para introduzir uma latência de 850 ms (com jitter de ±150 ms) e uma taxa de perda de pacotes de 5%.
# Injetando latência e perda de pacotes via ToxiProxy CLI
toxiproxy-cli toxic add payment_service \
  --type latency \
  --attribute latency=850 \
  --attribute jitter=150

toxiproxy-cli toxic add payment_service \
  --type loss \
  --attribute percent=5
Enter fullscreen mode Exit fullscreen mode

Hipótese do Experimento

"Sob latência média de 850 ms e perda de pacotes de 5% no gateway de pagamento, o Circuit Breaker configurado no Order Service deverá transicionar para o estado OPEN em menos de 5 segundos. Com isso, o fallback será disparado, enviando os pedidos para liquidação assíncrona com confirmação provisória, preservando a taxa de sucesso da rota acima de 99% e impedindo o esgotamento do pool de threads do Tomcat."

Delimitação do Blast Radius

  • Ambiente: Ambiente de staging espelhado com carga sintética de 350 requisições/s gerada via ferramenta de benchmarking.
  • Gatilho de Aborto (Emergency Stop): Se a taxa de respostas HTTP 500 subir acima de 2% no API Gateway ou a latência p99 exceder 1.500 ms, a injeção é cessada imediatamente.

4. Observabilidade e Resultados

DIAGRAMA 4: Transição de Estados do Circuit Breaker (Closed, Open e Half-Open)

Cronologia da Execução

Tempo Comportamento Registrado na Telemetria Ação dos Padrões de Resiliência
T+00:00 Estado estável: 350 req/s, latência p95 de 42 ms, taxa de erro de 0%. Sistema operando dentro dos parâmetros nominais.
T+01:00 Ativação dos tóxicos de latência e perda de pacotes no ToxiProxy. Elevação pontual na fila de conexões pendentes.
T+01:04 A taxa de chamadas lentas excede o limiar de 50% na janela deslizante. Circuit Breaker transiciona para OPEN.
T+01:05 Chamadas síncronas bloqueadas localmente via fast-fail. O método de Fallback entra em ação: registra o pedido em status pendente e repassa a liquidação para processamento assíncrono em fila.
T+01:06 - T+08:00 Carga de 350 req/s mantida sob falha da dependência. Latência p95 cai para 38 ms graças ao retorno imediato do fallback; zero esgotamento de threads.
T+08:00 Remoção do tóxico no ToxiProxy. O circuito transiciona para HALF-OPEN, valida as chamadas de teste e retorna ao estado CLOSED.

Configuração de Resiliência Aplicada

resilience4j.circuitbreaker:
  instances:
    paymentService:
      slidingWindowType: COUNT_BASED
      slidingWindowSize: 20
      minimumNumberOfCalls: 10
      failureRateThreshold: 50
      slowCallRateThreshold: 50
      slowCallDurationThreshold: 500ms
      waitDurationInOpenState: 10000ms
      permittedNumberOfCallsInHalfOpenState: 5
      automaticTransitionFromOpenToHalfOpenEnabled: true

resilience4j.timelimiter:
  instances:
    paymentService:
      timeoutDuration: 600ms
Enter fullscreen mode Exit fullscreen mode

Implementação do Padrão com Fallback Gracioso

@Service
public class OrderCheckoutService {

    private final PaymentClient paymentClient;
    private final PendingPaymentQueue pendingPaymentQueue;

    @CircuitBreaker(name = "paymentService", fallbackMethod = "processPaymentFallback")
    public CheckoutResponse processOrder(OrderRequest request) {
        PaymentResult result = paymentClient.authorize(request.getPaymentDetails());
        return CheckoutResponse.approved(request.getOrderId(), result.getTransactionId());
    }

    public CheckoutResponse processPaymentFallback(OrderRequest request, Throwable ex) {
        log.warn("Serviço de pagamento indisponível ou instável. Acionando fallback assíncrono.");
        pendingPaymentQueue.enqueueForAsyncProcessing(request);
        return CheckoutResponse.acceptedAsync(request.getOrderId(), 
            "Seu pedido foi recebido e está sendo liquidado em segundo plano.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Padrões Arquiteturais Validados

  • Circuit Breaker com Fast-Fail: Interrompeu a espera de rede, evitando bloqueio generalizado e exaustão do pool de threads.
  • Bulkhead (Isolamento de Recursos): A saturação da integração de pagamentos não comprometeu o catálogo de produtos ou endpoints de autenticação.
  • Retry com Backoff Exponencial e Jitter: Garantiu que o reprocessamento da fila de contingência não gerasse um pico repentino de carga (thundering herd) quando o gateway se recuperou.
  • Auto-Healing e Multi-AZ: Em testes adicionais de derrubada de nós, o pool de instâncias restabeleceu conexões com a réplica sem indisponibilidade de transações.

5. Conclusão e Lições de Cultura

A execução periódica de experimentos guiados pelo ChaosEngineeringMasterDeck transforma a postura operacional da organização.

Principais Lições Aprendidas

  • Suposições teóricas não substituem validação prática: Antes do teste, acreditava-se que os timeouts de rede padrão protegeriam a aplicação, quando na prática teriam derrubado o pool de conexões em poucos segundos sob carga moderada.
  • Cultura Blameless (Sem Culpa): Incidentes identificados durante os testes servem para aprimorar o sistema. Seguindo o modelo de Correction of Errors (COE), a equipe investiga causas sistêmicas por meio dos 5 Porquês, eliminando pontos únicos de falha de forma contínua.
  • Treinamento e Prontidão de Resposta: Conduzir simulações combate a atrofia de habilidades das equipes de engenharia e operações. Como bem pontuou Jesse Robbins, criador dos GameDays na Amazon: > "You don't choose the moment, the moment chooses you. You only choose how prepared you are when it does."

Engenharia do Caos não é quebrar coisas sem controle; é um método estruturado para assegurar previsibilidade e confiança na infraestrutura.

Nas palavras finais de Adrian Hornsby no Master Deck:

"Chaos Engineering won't make your system more robust, People will." (A Engenharia do Caos não tornará seu sistema mais robusto; as pessoas farão isso).


Referências e Leituras Recomendadas

  1. Principles of Chaos Engineering (principlesofchaos.org).
  2. Chaos Engineering on AWS: Building Resilient Systems — Adrian Hornsby.
  3. ByteByteGo: System Design Interview & Resilient Patterns — Alex Xu.
  4. Release It!: Design and Deploy Production-Ready Software — Michael T. Nygard.
  5. The Amazon Builders' Library: Challenges with Distributed Systems — AWS.

Top comments (0)