1

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çãoMelhor padrão
Consultar dados necessários na horaREST/gRPC síncrono
Enviar notificação depois de criar pedidoEvento assíncrono
Gerar relatório pesadoFila
Vários serviços precisam reagir ao mesmo fatoPub/Sub
Fluxo com várias etapas e compensaçãoSaga
Frontend acessando vários serviçosAPI Gateway ou BFF
Evitar falha em cascataCircuit Breaker
Reprocessar mensagens com segurançaIdempotê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.

Carregando publicação patrocinada...