Voltar para artigos
Arquitetura de Software

Mensageria: Quando um Gateway Lento Quase Quebrou a Integração com Fornecedores

Publicado em 27 de mar. de 2026
Mensageria: Quando um Gateway Lento Quase Quebrou a Integração com Fornecedores

Era quarta-feira, meio do expediente. O time de suporte começou a receber reclamações: pedidos estavam demorando horas para serem enviados aos fornecedores.

O problema parecia intermitente. Alguns pedidos fluíam normalmente, outros ficavam "presos" sem nenhum motivo aparente. O time de infraestrutura já tinha reiniciado os servidores duas vezes, mas o problema voltava.

Depois de algumas horas investigando os logs, a causa ficou clara: um dos nossos principais fornecedores estava com o gateway de integração lento.

Nota: A história contada acima é fictícia e foi criada apenas para se ter um entendimento melhor do assunto de forma prática.

O Problema em Poucas Linhas

O fluxo funcionava assim:

Sistema principal → chamada síncrona → Fornecedor A (rápido)
Sistema principal → chamada síncrona → Fornecedor B (rápido)
Sistema principal → chamada síncrona → Fornecedor C (lento ou fora do ar)

A decisão de qual fornecedor atenderia o pedido só era tomada após todas as respostas.

Resultado: o mais lento define o ritmo de todos.

E pior: quando um falha, todo o fluxo quebra.

Esse é um problema clássico de sistemas acoplados de forma síncrona.

O Impacto Real

  • Pedidos travados por minutos (ou horas)
  • Aumento de timeout e retrabalho
  • Sobrecarga no suporte
  • Experiência ruim para o usuário final

E o mais perigoso: o problema não estava no nosso sistema diretamente, mas em uma dependência externa.

A Virada de Chave

A pergunta que mudou tudo foi:

"Por que estamos esperando fornecedores externos para continuar nosso fluxo interno?"

A resposta era simples: não deveríamos estar.

A Solução: Mensageria com Filas

Redesenhamos o fluxo com um objetivo claro: desacoplar o sistema principal das integrações externas.

Novo fluxo:

  1. O pedido é registrado imediatamente
  2. O sistema publica mensagens para cada fornecedor
  3. Cada fornecedor é processado de forma independente
  4. Falhas não bloqueiam o fluxo principal

Agora, o sistema principal não depende mais do tempo de resposta dos fornecedores.

Como Funciona na Prática

  • Produtor: publica o pedido nas filas
  • Fila: armazena as mensagens de forma resiliente
  • Consumidor: processa cada fornecedor separadamente
  • Retry: reprocessa falhas com backoff

Se o Fornecedor C estiver lento, apenas o consumidor dele será impactado.

O restante do sistema continua funcionando normalmente.

Estratégia de Retentativas (Retry)

Implementamos uma política simples e eficiente:

  • Até 5 tentativas
  • Delay progressivo (backoff)
  • Após o limite → fila de falhas (dead-letter)

Isso evita:

  • Sobrecarga no fornecedor
  • Loop infinito de erro
  • Perda silenciosa de pedidos

Modelos de Mensageria

1. Fila (Point-to-Point)

Uma mensagem é consumida por apenas um consumidor.

Use quando:

  • Há responsabilidade única
  • O processamento não pode ser duplicado

Exemplos:

  • Envio de pedidos
  • Geração de boletos
  • Processamento de arquivos

2. Pub/Sub (Publish/Subscribe)

Uma mensagem é distribuída para múltiplos consumidores.

Use quando:

  • Vários sistemas precisam reagir ao mesmo evento

Exemplos:

  • Pedido criado → estoque, faturamento, logística
  • Eventos de domínio

Ferramenta Utilizada

RabbitMQ

Por que escolhemos:

  • Simples de começar
  • Extremamente estável
  • Suporte a múltiplos padrões de mensageria

Exemplo Prático (Node.js)

// Producer
const amqp = require('amqplib');

async function enviarPedidoParaFornecedor(pedido, fornecedorId) {
  const connection = await amqp.connect('amqp://localhost');
  const channel = await connection.createChannel();
  
  const queue = `fornecedor_${fornecedorId}`;
  const message = { 
    pedidoId: pedido.id, 
    itens: pedido.itens,
    tentativa: 1
  };
  
  await channel.assertQueue(queue, { durable: true });
  channel.sendToQueue(queue, Buffer.from(JSON.stringify(message)));
  
  console.log(`✅ Pedido ${pedido.id} enfileirado`);
  
  await channel.close();
  await connection.close();
}
// Consumer
async function processarFilaFornecedor(fornecedorId) {
  const connection = await amqp.connect('amqp://localhost');
  const channel = await connection.createChannel();
  
  const queue = `fornecedor_${fornecedorId}`;
  await channel.assertQueue(queue, { durable: true });
  
  channel.consume(queue, async (msg) => {
    const pedido = JSON.parse(msg.content.toString());
    
    try {
      await axios.post(`https://api.fornecedor${fornecedorId}.com/pedidos`, pedido, {
        timeout: 5000
      });
      
      channel.ack(msg);
      
    } catch (error) {
      if (pedido.tentativa < 5) {
        pedido.tentativa++;
        
        setTimeout(() => {
          channel.sendToQueue(queue, Buffer.from(JSON.stringify(pedido)));
        }, 5000 * pedido.tentativa);
        
      } else {
        await channel.sendToQueue('pedidos_falhos', Buffer.from(JSON.stringify(pedido)));
      }
      
      channel.ack(msg);
    }
  });
}

Uma Analogia Simples

Imagine que você está em um restaurante e faz um pedido que depende de três cozinhas diferentes:

  • Entrada → cozinha A (rápida)
  • Prato principal → cozinha B (rápida)
  • Sobremesa → cozinha C (lenta)

Agora imagine que o garçom só pode te entregar o pedido completo quando todas as cozinhas terminarem.

Se a sobremesa atrasar, você fica sem comer — mesmo com o resto pronto.

Esse era exatamente o nosso cenário.

Com mensageria, o modelo muda:

Cada cozinha recebe seu pedido separadamente e trabalha no seu tempo.
O restaurante não trava por causa de uma sobremesa atrasada.

👉 O sistema continua fluindo, mesmo com partes lentas.

Diagrama do Fluxo

Antes (Síncrono)

[ Sistema Principal ]
        ↓
 ┌───────────────┬───────────────┬───────────────┐
  ↓                        ↓                         ↓
 Fornecedor A            Fornecedor B             Fornecedor C (lento)
  (rápido)                 (rápido)                   (problema)
 
⛔ Espera todos → sistema bloqueado

---

Depois (Assíncrono com Filas)

[ Sistema Principal ]
        ↓
   (Publica mensagens)
        ↓
 ┌───────────────┬───────────────┬───────────────┐
  ↓                        ↓                         ↓
 Fila A                  Fila B                   Fila C
  ↓                        ↓                         ↓
 Consumer A              Consumer B               Consumer C
  ↓                        ↓                         ↓
 Fornecedor A            Fornecedor B             Fornecedor C (lento)

✅ Cada fluxo é independente
✅ Falhas não bloqueiam o sistema
✅ Retry isolado por fornecedor

Benefícios Imediatos

1. Sistema mais resiliente

Falhas externas não afetam mais o fluxo principal.

2. Melhor experiência do usuário

Pedidos são processados imediatamente, sem travar.

3. Time mais produtivo

Menos interrupções e menos retrabalho.

4. Integrações mais fáceis de manter

Cada fornecedor tem seu próprio consumidor, isolado dos outros.

Quando Usar Mensageria?

Use quando:

  • Você tem integrações com sistemas externos
  • Precisa processar tarefas em segundo plano
  • O sistema precisa continuar funcionando mesmo com falhas
  • Você precisa desacoplar serviços

Não use quando:

  • O sistema é muito simples
  • Não há necessidade de processamento assíncrono
  • A latência de milissegundos é crítica

Conclusão

A mensageria resolve problemas reais de sistemas distribuídos. No nosso caso, transformou um fluxo frágil em uma arquitetura resiliente.

Se você enfrenta problemas com timeouts, integrações lentas ou sistemas acoplados, considere usar filas.

É uma das ferramentas mais poderosas do ecossistema de software moderno.