Event-driven architecture
1. Fundamentos da Arquitetura Orientada a Eventos
A Arquitetura Orientada a Eventos (EDA) é um estilo arquitetural onde a comunicação entre componentes ocorre através da produção, detecção e consumo de eventos. Um evento representa uma mudança de estado significativa no sistema — algo que aconteceu no passado e não pode ser desfeito. Diferentemente de chamadas síncronas como REST ou RPC, onde o cliente bloqueia aguardando resposta, na EDA os componentes são fracamente acoplados e se comunicam de forma assíncrona.
Os componentes-chave da EDA incluem:
- Produtores: geram eventos quando algo relevante ocorre
- Consumidores: reagem a eventos de seu interesse
- Barramento de eventos: canal lógico que transporta eventos
- Brokers: infraestrutura que gerencia o roteamento e persistência dos eventos
Exemplo de evento em formato JSON:
{
"eventId": "a1b2c3d4",
"eventType": "OrderPlaced",
"timestamp": "2025-03-28T14:30:00Z",
"data": {
"orderId": "ORD-9876",
"customerId": "CUST-123",
"totalAmount": 250.00
}
}
2. Padrões de Comunicação e Topologias
Existem três padrões principais de comunicação baseada em eventos:
Event Notification: o produtor notifica consumidores sobre mudanças, sem incluir dados completos. Consumidores buscam dados adicionais se necessário.
Event Streaming: todos os eventos são persistidos em ordem cronológica, permitindo reprocessamento e auditoria completa.
Event Sourcing: o estado atual do sistema é derivado exclusivamente da sequência de eventos armazenados.
Quanto às topologias, temos:
- Mediator Topology: um orquestrador central coordena o fluxo de eventos entre produtores e consumidores
- Broker Topology: não há mediador central; cada consumidor decide como reagir aos eventos
Garantias de entrega variam:
At-most-once: evento pode ser perdido, nunca duplicado
At-least-once: evento sempre entregue, pode haver duplicatas
Exactly-once: entrega garantida sem perda nem duplicação
3. Escalabilidade e Resiliência com Event Sourcing
No Event Sourcing, o event store é a fonte única da verdade. Cada evento é imutável e representa uma transação. Para reconstruir o estado atual de uma entidade, basta reproduzir todos os eventos relacionados na ordem correta.
Exemplo de reconstrução de estado:
Eventos do agregado "Pedido-9876":
1. OrderPlanned { items: ["A", "B"], total: 200 }
2. PaymentReceived { amount: 200, method: "credit_card" }
3. OrderShipped { trackingCode: "BR123456789" }
Estado reconstruído:
{
orderId: "ORD-9876",
items: ["A", "B"],
status: "shipped",
totalPaid: 200
}
Para consultas otimizadas, utilizam-se projeções e read models — visões materializadas dos eventos que podem ser consultadas rapidamente. Em caso de falhas, o replay de eventos permite recuperar o estado exato do sistema, desde que os consumidores sejam idempotentes.
4. Gerenciamento de Consistência e Complexidade
Sistemas distribuídos baseados em eventos operam tipicamente com consistência eventual — após um período, todos os nós convergem para o mesmo estado. Isso contrasta com consistência forte, onde toda leitura retorna o dado mais recente.
Para transações distribuídas, o padrão Saga coordena múltiplos serviços através de eventos compensatórios:
Saga de Pedido:
1. Serviço de Pedidos: cria pedido (evento: OrderCreated)
2. Serviço de Pagamento: processa pagamento (evento: PaymentProcessed)
3. Serviço de Estoque: reserva itens (evento: InventoryReserved)
4. Se falha no estoque → evento: PaymentRefunded (ação compensatória)
5. Se falha no pagamento → evento: OrderCancelled (ação compensatória)
Versionamento de eventos é crítico para evolução de esquemas. Estratégias comuns incluem:
- Adicionar novos campos opcionais sem quebrar consumidores antigos
- Criar novas versões de tipos de evento (ex: OrderPlacedV2)
- Utilizar schema registries para validar compatibilidade
5. Infraestrutura e Ferramentas para EDA
A escolha do broker impacta diretamente o design da arquitetura:
| Ferramenta | Caso de uso ideal | Trade-offs |
|---|---|---|
| Apache Kafka | Event streaming, replay, alta throughput | Complexidade operacional, latência maior |
| RabbitMQ | Roteamento flexível, mensageria tradicional | Menor throughput em streaming |
| AWS SQS/SNS | Serverless, integração com AWS | Vendor lock-in, limitações de tamanho |
Dead letter queues (DLQs) armazenam eventos que falharam repetidamente, permitindo análise posterior:
Configuração típica:
- maxRetries: 3
- retryDelay: 5 segundos (exponencial: 5s, 10s, 20s)
- deadLetterQueue: "orders-dlq"
Para observabilidade, ferramentas como OpenTelemetry permitem rastrear fluxos completos de eventos através de múltiplos serviços.
6. Padrões Avançados e Integração com Outras Arquiteturas
CQRS (Command Query Responsibility Segregation) complementa EDA separando comandos (escrita) de consultas (leitura). Eventos gerados por comandos alimentam read models otimizados para consultas.
Em migrações de sistemas monolíticos, o padrão Strangler Fig permite gradualmente extrair funcionalidades para microserviços orientados a eventos:
Fase 1: Monólito + evento de "pedido criado" publicado
Fase 2: Novo serviço de notificação consome o evento
Fase 3: Novo serviço de faturamento consome o mesmo evento
Fase 4: Monólito é desativado gradualmente
Padrões de resiliência incluem:
- Bulkhead: isolar consumidores em pools de recursos separados
- Timeout: limitar tempo de processamento de cada evento
- Circuit Breaker: interromper consumo quando serviço downstream falha
7. Casos de Uso e Considerações Finais
EDA brilha em cenários como:
- IoT: dispositivos geram milhões de eventos de sensores
- Pipelines de dados: processamento em tempo real de streams
- Sistemas de notificação: alertas baseados em eventos de negócio
- E-commerce: processamento assíncrono de pedidos e pagamentos
Armadilhas comuns incluem:
- Complexidade de depuração: rastrear fluxos de eventos entre múltiplos serviços
- Latência: consistência eventual pode não atender requisitos de tempo real
- Custo operacional: infraestrutura de brokers e armazenamento de eventos
Evite EDA quando:
- Requisitos de consistência imediata são inegociáveis
- O sistema é simples e não se beneficia do desacoplamento
- A equipe não tem maturidade para operar brokers e lidar com eventual consistency
A Arquitetura Orientada a Eventos oferece escalabilidade, resiliência e desacoplamento incomparáveis para sistemas distribuídos modernos, mas exige planejamento cuidadoso e investimento em ferramentas de observabilidade e governança de eventos.
Referências
- Event-Driven Architecture - Martin Fowler — Artigo seminal explicando conceitos fundamentais de EDA e padrões associados
- Apache Kafka Documentation — Documentação oficial do Kafka, principal plataforma de event streaming
- Pattern: Event Sourcing - Microsoft Azure — Guia prático sobre implementação de Event Sourcing com exemplos
- Saga Pattern - Chris Richardson — Explicação detalhada do padrão Saga para transações distribuídas
- CQRS Pattern - Microsoft Learn — Documentação oficial sobre CQRS e sua integração com EDA
- RabbitMQ Tutorials — Tutoriais práticos sobre mensageria com RabbitMQ para iniciantes
- Event-Driven Architecture on AWS — Visão geral de serviços AWS para implementação de EDA serverless