Referência: Um Serviço Axum de Alto Rendimento
Um layout de referência para uma API HTTP sensível à latência: Axum 0.8, Tokio 1.x, sqlx 0.8, serde 1.0 e observabilidade desde o primeiro dia - visando milhares de RPS por pod com comportamento de pool previsível e rollouts seguros.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
orders-api/
crates/
orders-domain/ # lógica pura, sem axum/sqlx na API pública
orders-infra/ # clientes sqlx, redis
orders-api/ # binário: rotas, middleware, main
migrations/
deploy/
Dockerfile # rust:1.97.0, edição 2024
helm/Quando usar isto:
- Serviço Greenfield de alto RPS
- Ensinar a equipe o padrão HTTP da frota
- Linha de base RFC para novo ADR de API
- Comparação de regressão de desempenho
Exemplo de Trabalho
// crates/orders-api/src/main.rs
use axum::{routing::get, Router};
use sqlx::postgres::PgPoolOptions;
use std::net::SocketAddr;
use tower_http::trace::TraceLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::from_default_env())
.with(tracing_subscriber::fmt::layer().json())
.init();
let pool = PgPoolOptions::new()
.max_connections(20)
.connect(&std::env::var("DATABASE_URL")?)
.await?;
let app = Router::new()
.route("/health/ready", get(|| async { "ok" }))
.route("/v1/orders/:id", get(orders_infra::get_order))
.layer(TraceLayer::new_for_http())
.with_state(pool);
let addr: SocketAddr = "0.0.0.0:8080".parse()?;
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app)
.with_graceful_shutdown(shutdown_signal())
.await?;
Ok(())
}
async fn shutdown_signal() {
tokio::signal::ctrl_c().await.ok();
}# Notas de implantação
docker build -t orders-api:sha-$(git rev-parse --short HEAD) .
# Canário 10% com guardrail p95 < 120ms; pool_acquire_p95 < 30msAnálise Profunda
Escolhas de Arquitetura
- Divisão de crates - Lógica de domínio testável sem servidor HTTP.
- Pool de conexões - Tamanho a partir do teste de carga: limite superior
(contagem_de_núcleos * 2) + reserva, limitado pormax_connectionsdo Postgres. - Middleware -
TraceLayerpara IDs de requisição; compressão apenas se medido como vantajoso. - Encerramento -
with_graceful_shutdownmaispreStopdo K8s para drenagem do LB.
Checklist de Desempenho
- Evitar alocações por requisição no caminho crítico (
Bytes, reutilizar buffers). spawn_blockingapenas para trabalho intensivo de CPU.- Consultas indexadas validadas com
EXPLAINno teste de carga de staging.
Operações
- Prontidão: ping do DB + Redis opcional.
- Liveness: apenas processo ativo (evitar mortes por instabilidade do DB).
- Dashboards: RPS, p95, aquisição de pool, contador de pânico, anotação SHA de implantação.
Armadilhas
- Concepção errônea de pool por worker - O pool
sqlxé compartilhado entre tarefas no processo. Correção: Um pool por processo, ajustarmax_connections. - Build de depuração em produção - Colapso de rendimento. Correção:
cargo build --releasecom perfil LTO considerado. - Sem encerramento gracioso - 502 durante rollouts. Correção: Drenar +
preStop. - Respostas JSON gigantes - Picos de memória. Correção: Paginação e streaming onde necessário.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Actix-web | Legado da equipe em Actix | Ecossistema Tower Greenfield |
| gRPC (tonic) | RPC interno leste-oeste | Clientes de navegador públicos |
| Cache de proxy Sidecar | JSON estático com muitas leituras | Respostas de autenticação personalizadas |
FAQs
Quantos RPS por pod?
Medir; o layout de referência visa 2-5k RPS de leitura simples em 2 vCPUs com pool ajustado - não é uma garantia.
Escala horizontal?
Preferir escalar horizontalmente; observar total de conexões do DB = pods * max do pool.
Consultas sqlx em tempo de compilação?
Sim, com dados offline; CI valida contra a versão da migração.
Limitação de taxa (Rate limiting)?
Middleware Tower ou gateway de borda; documentar em ADR para APIs públicas.
Multi-região?
Réplicas de leitura com roteamento; escrita com sticky de região; pool por endpoint de DB da região.
Relacionados
- Roteamento Axum - manipuladores
- Pool de Conexões - ajuste de pool
- Encerramento Gracioso - segurança de implantação
- Benchmarks de Latência e Rendimento - medição
- Melhores Práticas de Entrega - lançamento
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4 e Polars 0.46+.