Especialização em Backend com Go & Gin • Gin Framework & Go 1.22+ • GORM, Clean Architecture, Concorrência e Alta Performance


🗺️ Mapa Conceitual do Tópico

flowchart TD
    A["Cliente HTTP / Frontend"] --> B["API Gateway / Router"]
    B --> C["Controller / Handler"]
    C --> D["Service Layer (Regras de Negócio)"]
    D --> E["Repository / ORM (Persistência)"]
    E --> F["Banco de Dados / Cache"]

    subgraph ARQ["Arquitetura do Capítulo"]
        G["Conceito: Mensageria Assíncrona com RabbitMQ ou Apache Kafka"]
        H["Segurança, Validação e Resiliência"]
        I["Alta Performance e Escalabilidade"]
    end

    D --> ARQ

    style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style B fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    style C fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style D fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
    style E fill:#fce4ec,stroke:#e91e63,stroke-width:2px
    style F fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px

🏛️ 1. Fundamentos Técnicos de Mensageria Assíncrona com RabbitMQ ou Apache Kafka

Mensageria assíncrona desacopla o produtor de um evento do(s) consumidor(es), permitindo que serviços processem trabalho sem bloquear a requisição HTTP original e sem conhecimento direto uns dos outros. RabbitMQ e Apache Kafka resolvem esse problema com modelos de arquitetura fundamentalmente diferentes, e escolher entre eles é uma decisão de design, não uma preferência estilística:

  • RabbitMQ é um message broker tradicional (protocolo AMQP): mensagens são roteadas por exchanges até filas, entregues a um consumidor e removidas da fila após confirmação (Ack). É ideal para filas de tarefas, roteamento condicional complexo e cenários onde a mensagem representa um comando único a ser processado uma vez.
  • Apache Kafka é uma plataforma de streaming de eventos: mensagens são anexadas a um log de commit imutável, particionado, e retidas por um período configurável independentemente de terem sido consumidas. Múltiplos grupos de consumidores podem ler o mesmo tópico de forma independente e reprocessar o histórico. É ideal para event sourcing, auditoria e pipelines de dados de altíssimo throughput.

Em Go, o cliente idiomático para RabbitMQ é github.com/rabbitmq/amqp091-go. O publicador declara a fila (QueueDeclare, idempotente) e publica com PublishWithContext, definindo DeliveryMode: amqp.Persistent para que a mensagem sobreviva a um restart do broker. Do lado do consumidor, a confiabilidade depende do acknowledgement manual: msg.Ack(false) confirma que a mensagem foi processada com sucesso e pode ser removida da fila; se o worker falhar ou crashar antes do Ack, o RabbitMQ reenfileira automaticamente a mensagem para outro consumidor — chamando msg.Nack(false, true) explicitamente quando o processamento falha de forma recuperável (o segundo parâmetro requeue=true decide se ela volta para a fila ou é descartada/roteada para DLQ).

Esse modelo “pelo menos uma vez” (at-least-once) implica que handlers de consumo devem ser idempotentes — processar a mesma mensagem duas vezes (por exemplo, após um crash entre o processamento e o Ack) não pode gerar efeito colateral duplicado (cobrar duas vezes, criar dois pedidos).

Um problema clássico de integração é o dual-write: gravar no banco de dados e publicar um evento são duas operações contra sistemas diferentes que não compartilham uma transação — se o processo cair entre as duas, o sistema fica inconsistente (dado salvo, evento nunca publicado, ou vice-versa). O padrão Outbox resolve isso: o evento é gravado como uma linha em uma tabela outbox_events, na mesma transação SQL que grava o dado de negócio (atomicidade garantida pelo próprio banco); um processo separado (poller ou CDC) lê a tabela outbox periodicamente e publica as mensagens pendentes no broker, marcando-as como processadas — garantindo consistência eventual sem exigir transação distribuída (2PC).

Para lidar com mensagens que falham repetidamente (payload malformado, bug no handler — as chamadas “poison messages”), configura-se uma Dead Letter Exchange (DLX): a fila principal declara os argumentos x-dead-letter-exchange e x-dead-letter-routing-key; após esgotar um número de tentativas (ou expirar via x-message-ttl), o RabbitMQ roteia automaticamente a mensagem para uma fila de dead-letter (DLQ), isolando-a para inspeção manual sem travar o processamento das mensagens saudáveis que vêm atrás dela na fila principal.


💻 2. Código de Demonstração Corporativo

package messaging

import (
    "context"
    "encoding/json"
    "log"

    amqp "github.com/rabbitmq/amqp091-go"
)

type PedidoCriadoEvent struct {
    PedidoID uint    `json:"pedido_id"`
    Total    float64 `json:"total"`
}

// PublicarPedidoCriado serializa o evento e publica de forma persistente,
// sobrevivendo a um restart do broker (DeliveryMode: Persistent).
func PublicarPedidoCriado(ch *amqp.Channel, evento PedidoCriadoEvent) error {
    body, err := json.Marshal(evento)
    if err != nil {
        return err
    }
    return ch.PublishWithContext(context.Background(), "", "pedidos_queue", false, false, amqp.Publishing{
        ContentType:  "application/json",
        DeliveryMode: amqp.Persistent,
        Body:         body,
    })
}

// ConsumirPedidos processa mensagens com Ack manual: só remove da fila após
// sucesso; em falha recuperável, Nack com requeue devolve para reprocessamento.
func ConsumirPedidos(msgs <-chan amqp.Delivery) {
    for d := range msgs {
        var evento PedidoCriadoEvent
        if err := json.Unmarshal(d.Body, &evento); err != nil {
            d.Nack(false, false) // payload malformado: descarta (vai para DLX, se configurada)
            continue
        }
        if err := processarPedido(evento); err != nil {
            log.Printf("falha ao processar pedido %d: %v", evento.PedidoID, err)
            d.Nack(false, true) // erro recuperável: reenfileira
            continue
        }
        d.Ack(false)
    }
}

🔗 Recursos Pedagógicos do Capítulo 14

Recurso Didático Finalidade Link de Acesso
📊 Slides de Aula Apresentação visual interativa com Dark Mode e suporte a teclado Ver Slides
🧠 Quiz Formativo Teste interativo de fixação com feedback imediato por alternativa Fazer Quiz
💻 Exemplos de Código Demonstrações funcionais com código executável Ver Exemplos
🧩 Exercícios em 4 Níveis Lista progressiva de fixação com gabarito em bloco colapsável Resolver Exercícios

⬅️ Capítulo Anterior 📚 Sumário de Tópicos Próximo Capítulo ➡️