Seu servidor Rust é ideal? Vamos verificar
Você escreveu um servidor em Rust que processa milhares de requisições por segundo. O compilador está satisfeito, o clippy silencioso, os testes passam. Mas o que acontecerá se o banco de dados for desligado repentinamente? Ou se a placa de rede começar a falhar? Ou se o disco ficar cheio?
No teste tradicional, verificamos se o código funciona como esperado. A engenharia do caos é diferente: verificamos se o sistema sobrevive apesar de tudo. E o Rust, com seu foco em confiabilidade e desempenho, é o palco ideal para esses experimentos.
Este artigo não é uma recontagem entediante da documentação. Vamos percorrer o caminho da teoria à prática: mostrarei como implementar engenharia do caos para aplicações Rust usando ferramentas e código reais.
O que é Engenharia do Caos e por que é importante para o desenvolvedor Rust?
A engenharia do caos é uma disciplina de experimentos em sistemas distribuídos, com o objetivo de identificar seus pontos fracos antes que eles se manifestem em produção. A Netflix, considerada pioneira nessa abordagem, usa a ferramenta Chaos Monkey para desligar servidores aleatoriamente.
Por que isso é importante especificamente para Rust? Porque o Rust é frequentemente escolhido para sistemas críticos:
- Serviços de rede (proxies, balanceadores de carga, gateways de API)
- Sistemas embarcados (IoT, automóveis)
- Nós de blockchain e sistemas financeiros
- Processamento de fluxo de dados
Em todos esses casos, o custo de um erro é alto. A engenharia do caos ajuda a garantir que sua aplicação Rust sobreviva não apenas à carga normal, mas também ao caos do mundo real.
Ferramentas para Engenharia do Caos no ecossistema Rust
Embora o ecossistema Rust seja mais jovem que o do Java ou Go, já temos várias bibliotecas maduras para introduzir o caos.
| Ferramenta | Finalidade | Status |
|---|---|---|
tokio-rs/bytes | Emulação de atrasos de rede | Ativo |
fault-injection | Injeção de panics e erros | Estável |
simulation | Emulação de falhas de disco/rede | Experimental |
chaostoolkit | Framework para cenários de caos | Suporte via HTTP API |
Vamos nos concentrar em um exemplo prático usando fault-injection e emulação de problemas de rede.
Exemplo prático: "Apague o incêndio" em um serviço Rust
Suponha que temos um servidor HTTP simples em axum que faz algo (por exemplo, chama uma API externa). Queremos testar como ele se comportará se o serviço externo ficar indisponível ou começar a responder com atraso.
Passo 1: Servidor básico com uma "falha"
Vamos escrever um servidor que faz uma requisição para httpbin.org (simulando um serviço externo):
use axum::{Router, routing::get, response::Json};use reqwest::Client;use std::sync::Arc;use serde_json::Value;
#[tokio::main]async fn main() { let client = Arc::new(Client::new());
let app = Router::new() .route("/fetch", get(handler)) .with_state(client);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap();}
async fn handler(client: Arc<Client>) -> Result<Json<Value>, (StatusCode, String)> { let resp = client.get("https://httpbin.org/uuid") .timeout(std::time::Duration::from_secs(5)) .send() .await .map_err(|e| (StatusCode::SERVICE_UNAVAILABLE, e.to_stri