Padrões de Comunicação - Microserviços
A comunicação entre microserviços é basicamente como um serviço conversa com outro para cumprir uma regra de negócio.
Em uma arquitetura monolítica, uma classe chama outra diretamente. Em microserviços, essa chamada atravessa a rede, então surgem problemas como latência, falha parcial, timeout, duplicidade, ordem de mensagens e consistência eventual.
1. Dois grandes tipos de comunicação
1.1 Comunicação síncrona
Um serviço chama outro e fica esperando a resposta.
Exemplo:
API Pedidos -> API Clientes
A API de Pedidos pergunta:
"Esse cliente pode comprar?"
A API de Clientes responde:
"Sim" ou "Não"
Enquanto não recebe resposta, a API de Pedidos fica parada aguardando.
Exemplos comuns
REST
gRPC
GraphQL
HTTP
Quando usar
Use quando a resposta é necessária na hora para continuar o fluxo.
Exemplo:
Para finalizar um pedido, preciso saber agora se o cliente está bloqueado.
Vantagens
É simples de entender, implementar e debugar.
Problemas
Se o serviço chamado estiver lento ou fora do ar, o serviço chamador também sofre.
Exemplo:
API Pedidos depende da API Clientes.
Se Clientes cai, Pedidos pode começar a falhar também.
Isso cria o famoso problema de acoplamento temporal: os dois serviços precisam estar disponíveis ao mesmo tempo.
1.2 Comunicação assíncrona
Um serviço envia uma mensagem/evento e não fica esperando o processamento imediato.
Exemplo:
API Pedidos -> Fila/Event Broker -> API Notificações
A API de Pedidos publica:
PedidoCriado
Depois, a API de Notificações consome esse evento e envia e-mail, push, WhatsApp etc.
Exemplos comuns
RabbitMQ
Kafka
Amazon SQS
Google Pub/Sub
Azure Service Bus
Quando usar
Use quando o processamento pode acontecer depois, sem travar o fluxo principal.
Exemplo:
Pedido foi criado.
Depois disso, posso enviar notificação, atualizar relatório, gerar log, integrar com outro sistema.
Vantagens
Aumenta resiliência. Se o serviço consumidor estiver fora, a mensagem pode ficar na fila para ser processada depois.
Problemas
É mais difícil de rastrear, debugar e garantir consistência. Você precisa lidar com duplicidade, reprocessamento e falhas.
2. Padrão Request/Response
Esse é o padrão mais tradicional.
Serviço A faz uma requisição para Serviço B.
Serviço B responde imediatamente
Exemplo:
GET /clientes/123
Resposta:
{
"id": 123,
"nome": "Cliente Teste",
"bloqueado": false
}
Quando faz sentido
Quando um serviço realmente precisa da informação naquele momento.
Exemplo:
API Pedidos precisa consultar o limite de crédito do cliente antes de aprovar o pedido.
Cuidados
Sempre defina:
timeout
retry controlado
circuit breaker
fallback
tratamento de erro
Um erro comum é deixar uma chamada HTTP sem timeout adequado. Isso pode travar threads e derrubar o serviço aos poucos.
3. Padrão Event-Driven
Nesse padrão, os serviços se comunicam por eventos.
Um evento representa algo que já aconteceu.
Exemplos:
PedidoCriado
PagamentoAprovado
NotaFiscalEmitida
ClienteBloqueado
EstoqueAtualizado
Fluxo:
API Pedidos publica PedidoCriado
API Estoque consome PedidoCriado
API Financeiro consome PedidoCriado
API Notificações consome PedidoCriado
Cada serviço reage ao evento conforme sua responsabilidade.
Exemplo de evento
{
"eventId": "abc-123",
"eventType": "PedidoCriado",
"pedidoId": 987,
"clienteId": 123,
"valorTotal": 1500.00,
"createdAt": "2026-06-04T10:30:00"
}
Quando usar
Quando vários serviços precisam saber que algo aconteceu, mas o serviço original não precisa controlar todos os próximos passos diretamente.
Exemplo ruim com REST
API Pedidos chama API Estoque
API Pedidos chama API Financeiro
API Pedidos chama API Notificações
API Pedidos chama API Relatórios
A API Pedidos fica acoplada a tudo.
Melhor com eventos
API Pedidos publica PedidoCriado
Os outros serviços decidem o que fazer.
4. Padrão Pub/Sub
Pub/Sub significa Publish/Subscribe.
Um serviço publica uma mensagem em um tópico, e vários serviços podem receber essa mensagem.
Publisher -> Topic -> Subscribers
Exemplo:
Pedidos publica PedidoCriado
Estoque escuta PedidoCriado
Financeiro escuta PedidoCriado
Notificações escuta PedidoCriado
Quando usar
Quando um mesmo evento interessa a vários serviços.
Exemplo prático
PedidoCriado
Pode interessar para:
Estoque
Financeiro
CRM
Relatórios
Notificações
Auditoria
5. Padrão Queue / Fila
Fila é diferente de Pub/Sub.
Na fila, normalmente uma mensagem é processada por um consumidor dentro de um grupo.
Produtor -> Fila -> Consumidor
Exemplo:
API Relatórios envia tarefa para fila
Worker de relatórios processa
Quando usar
Quando você quer distribuir trabalho.
Exemplo:
Gerar PDF
Enviar e-mail
Processar lote
Integrar pedidos
Recalcular ranking
Sincronizar dados
Exemplo
{
"jobType": "GerarRelatorioPedido",
"pedidoId": 987
}
6. Padrão Saga
Saga é usado quando uma operação envolve vários serviços e você precisa coordenar uma transação distribuída.
Exemplo de compra:
1. Criar pedido
2. Reservar estoque
3. Processar pagamento
4. Emitir nota
5. Enviar confirmação
Em monolito, talvez isso fosse uma transação única no banco.
Em microserviços, cada serviço tem seu próprio banco. Não dá para simplesmente usar uma transação SQL única entre todos.
A Saga resolve isso com uma sequência de passos e compensações.
6.1 Saga Coreografada
Cada serviço reage a eventos.
PedidoCriado
-> Estoque reserva
-> EstoqueReservado
-> Pagamento processa
-> PagamentoAprovado
-> Nota emite
Se der erro:
PagamentoRecusado
-> Estoque libera reserva
-> Pedido cancelado
Vantagem
Menos centralização.
Problema
O fluxo fica espalhado em vários serviços. Pode ser difícil entender o processo completo.
6.2 Saga Orquestrada
Existe um serviço orquestrador controlando o fluxo.
Orquestrador de Pedido
-> chama Estoque
-> chama Pagamento
-> chama Nota Fiscal
-> finaliza pedido
Vantagem
Mais fácil visualizar e controlar o fluxo.
Problema
O orquestrador pode virar um ponto central complexo.
7. Padrão API Gateway
O API Gateway fica na frente dos microserviços.
Cliente Web/Mobile -> API Gateway -> Microserviços
Ele pode cuidar de:
Autenticação
Autorização
Rate limit
Logs
Roteamento
Agregação de respostas
Versionamento
Exemplo:
App chama /dashboard
Gateway consulta Pedidos, Clientes e Financeiro
Gateway devolve uma resposta consolidada
Quando usar
Quando você tem vários microserviços e não quer que o frontend conheça todos diretamente.
8. Padrão BFF
BFF significa Backend For Frontend.
É parecido com API Gateway, mas específico para cada tipo de cliente.
Exemplo:
BFF Web
BFF Mobile
BFF Admin
O mobile pode precisar de uma resposta menor e otimizada. O web pode precisar de mais dados.
App Mobile -> BFF Mobile -> Microserviços
Painel Web -> BFF Web -> Microserviços
Quando usar
Quando diferentes frontends precisam de formatos de resposta diferentes.
9. Padrão Circuit Breaker
Esse padrão evita que um serviço fique insistindo em chamar outro serviço que está falhando.
Exemplo:
API Pedidos chama API Clientes
API Clientes começa a falhar
Circuit Breaker abre
API Pedidos para de chamar temporariamente
Estados comuns:
Closed: chamadas normais
Open: chamadas bloqueadas temporariamente
Half-open: testa se o serviço voltou
Por que é importante
Sem circuit breaker, um serviço instável pode derrubar outros em cascata.
10. Retry
Retry é tentar novamente quando uma chamada falha.
Exemplo:
Tentativa 1 falhou
Aguarda 500ms
Tentativa 2 falhou
Aguarda 1s
Tentativa 3 falhou
Desiste
Cuidado importante
Retry mal configurado pode piorar o problema.
Se um serviço já está sobrecarregado, muitos retries podem aumentar ainda mais a carga.
Use com:
limite de tentativas
backoff
jitter
timeout
idempotência
11. Idempotência
Idempotência significa que executar a mesma operação mais de uma vez gera o mesmo resultado final.
Isso é essencial em comunicação assíncrona, porque mensagens podem ser entregues mais de uma vez.
Exemplo problemático:
Mensagem: Debitar R$ 100
Se processar duas vezes:
Debita R$ 200
Melhor:
Mensagem: ProcessarPagamento eventId=abc-123
O serviço verifica se abc-123 já foi processado.
Se já foi, ignora.
Estratégia comum
Criar tabela de controle:
processed_events
Com campos:
event_id
event_type
processed_at
status
12. Consistência eventual
Em microserviços, nem sempre todos os dados estarão atualizados ao mesmo tempo.
Exemplo:
Pedido foi criado agora.
Relatório pode demorar alguns segundos para mostrar esse pedido.
Isso é consistência eventual.
Quando é aceitável
Relatórios
Dashboards
Notificações
Históricos
Auditoria
Sincronizações
Quando pode não ser aceitável
Validação de limite de crédito
Bloqueio de cliente
Autorização de pagamento
Controle rígido de estoque
Nesses casos, talvez comunicação síncrona ou reserva transacional seja mais adequada.
13. Comparação prática
| Situação | Melhor padrão |
|---|---|
| Consultar dados necessários na hora | REST/gRPC síncrono |
| Enviar notificação depois de criar pedido | Evento assíncrono |
| Gerar relatório pesado | Fila |
| Vários serviços precisam reagir ao mesmo fato | Pub/Sub |
| Fluxo com várias etapas e compensação | Saga |
| Frontend acessando vários serviços | API Gateway ou BFF |
| Evitar falha em cascata | Circuit Breaker |
| Reprocessar mensagens com segurança | Idempotência |
14. Exemplo completo: criação de pedido
Imagine um sistema com:
Pedidos
Clientes
Estoque
Financeiro
Notificações
Relatórios
Um fluxo equilibrado poderia ser:
1. App envia pedido para API Pedidos
2. API Pedidos consulta API Clientes de forma síncrona
- cliente está bloqueado?
- limite permite?
3. API Pedidos cria o pedido
4. API Pedidos publica evento PedidoCriado
5. API Estoque consome PedidoCriado e reserva produtos
6. API Financeiro consome PedidoCriado e registra cobrança
7. API Notificações consome PedidoCriado e envia mensagem
8. API Relatórios consome PedidoCriado e atualiza indicadores
Aqui temos uma mistura:
Síncrono para o que é obrigatório na hora.
Assíncrono para o que pode acontecer depois.
Esse costuma ser o melhor caminho.
15. Erros comuns em microserviços
Erro 1: transformar microserviços em monolito distribuído
Isso acontece quando um serviço depende de vários outros para qualquer operação simples.
Exemplo ruim:
API A chama API B
API B chama API C
API C chama API D
API D chama API E
Resultado:
Lento
Frágil
Difícil de debugar
Erro 2: usar REST para tudo
Nem tudo precisa de resposta imediata.
Exemplo ruim:
Criar pedido só termina depois de enviar e-mail, atualizar relatório e registrar auditoria.
Melhor:
Cria pedido
Publica eventos
Outros serviços processam depois
Erro 3: usar evento para tudo
Também é ruim.
Algumas decisões precisam ser tomadas na hora.
Exemplo:
Cliente está bloqueado?
Produto existe?
Usuário tem permissão?
Nesses casos, chamada síncrona pode ser mais simples e correta.
Erro 4: não tratar duplicidade
Em filas e eventos, assuma que a mensagem pode chegar mais de uma vez.
Regra prática:
Todo consumer deve ser idempotente.
Erro 5: não ter rastreabilidade
Em microserviços, uma requisição pode passar por vários serviços.
Use:
correlationId
traceId
logs estruturados
monitoramento
tracing distribuído
Exemplo:
{
"traceId": "req-789",
"pedidoId": 987,
"service": "api-pedidos",
"message": "Pedido criado"
}
16. Regra prática para decidir
Use esta pergunta:
Eu preciso da resposta agora para continuar?
Se sim:
Comunicação síncrona
REST/gRPC
Timeout
Circuit breaker
Fallback
Se não:
Comunicação assíncrona
Evento/Fila
Idempotência
Retry
Dead Letter Queue
17. Dead Letter Queue
DLQ é uma fila para mensagens que não conseguiram ser processadas.
Exemplo:
Mensagem falhou 5 vezes
Vai para DLQ
Time técnico analisa depois
Sem DLQ, mensagens problemáticas podem ficar travando o consumo da fila.
18. Resumo mental
Pense assim:
REST/gRPC = preciso conversar agora
Fila = preciso mandar alguém fazer um trabalho
Evento = preciso avisar que algo aconteceu
Pub/Sub = vários interessados precisam saber
Saga = preciso coordenar vários passos
Gateway/BFF = preciso proteger e organizar acesso externo
Circuit Breaker = preciso evitar efeito dominó
Idempotência = preciso sobreviver a duplicidade
DLQ = preciso lidar com mensagens problemáticas
19. Exemplo em termos de código
Chamada síncrona
ClienteResponse cliente = clienteClient.buscarCliente(clienteId);
if (cliente.isBloqueado()) {
throw new ClienteBloqueadoException();
}
pedidoRepository.save(pedido);
Aqui o pedido depende da resposta do cliente.
Comunicação assíncrona
pedidoRepository.save(pedido);
eventPublisher.publish(new PedidoCriadoEvent(
pedido.getId(),
pedido.getClienteId(),
pedido.getValorTotal()
));
Depois outro serviço consome:
@RabbitListener(queues = "pedido-criado")
public void consumir(PedidoCriadoEvent event) {
if (eventoJaProcessado(event.getEventId())) {
return;
}
notificacaoService.enviarConfirmacao(event.getPedidoId());
marcarComoProcessado(event.getEventId());
}
20. Conclusão
A melhor arquitetura normalmente não escolhe apenas um padrão.
Ela combina:
REST/gRPC para decisões imediatas
Eventos para propagar acontecimentos
Filas para processamentos demorados
Saga para fluxos distribuídos
Gateway/BFF para entrada dos clientes
Circuit breaker, retry e timeout para resiliência
Idempotência e
DLQ para segurança operacional
A regra principal é:
Não faça um serviço depender de outro sem necessidade.
Quanto menos dependência direta, mais resiliente tende a ser o sistema.