Mensageria com RabbitMQ e Golang - Conceitos e Primeiro Contato

Published: (December 10, 2025 at 08:05 AM EST)
6 min read
Source: Dev.to

Source: Dev.to

Introdução

A comunicação entre sistemas mudou bastante nos últimos anos. Antes, era comum que uma aplicação chamasse outra diretamente e esperasse sua resposta. Isso funcionava, mas só até certo ponto. Quanto maior o sistema, maior o acoplamento e menor a tolerância a falhas. Hoje, quando falamos em microsserviços, escalabilidade e resiliência, surge uma alternativa que atende diversos cenários: a mensageria.

A ideia central é simples. Em vez de depender de uma resposta imediata, o serviço envia uma mensagem para uma fila e segue sua vida. Outro serviço, quando puder, lê essa mensagem e faz o trabalho necessário. Isso torna a aplicação mais leve, mais modular e mais preparada para lidar com períodos de carga alta.

Neste artigo, vamos entender o básico sobre mensageria, aprender como usar o RabbitMQ para organizar o fluxo de mensagens e criar exemplos práticos em Go.

O que é Mensageria e por que ela é tão útil

Mensageria é o padrão de comunicação onde sistemas conversam através do envio e consumo de mensagens, e não por chamadas diretas. Isso resolve alguns problemas comuns em arquiteturas tradicionais.

Imagine um serviço de API que precisa realizar diversas etapas a partir de uma única requisição, sendo que uma delas (ou mais) pode sofrer com lentidão devido a conexão instável, grande volume de dados ou processamento mais pesado. Se for feito de forma síncrona, basta um desses passos ficar lento para o serviço todo travar, ou até mesmo ocasionar erros.

A mensageria permite deslocar essas tarefas para outro componente. Assim, a API recebe a requisição, separa o que precisa ser feito naquele momento (processamento síncrono) e o que não precisa ser concluído antes do retorno da API (processamento assíncrono).

Por exemplo, se houver a necessidade dessa requisição enviar um email ao final, a API pode retornar uma mensagem informando que o email será enviado, e designar o disparo desse email a um serviço de mensageria que será executado de forma independente.

Um cenário comum desse exemplo seria o envio do e‑mail de boas‑vindas após um cadastro. Em vez de ser feito de forma síncrona na requisição, pode ser criada uma estrutura similar a esta:

{
  "usuario_id": 123,
  "acao": "enviar_email_boas_vindas"
}

Essa mensagem vai para uma fila. Depois, outro serviço lê a fila e envia o e‑mail.

O que é RabbitMQ e como ele funciona

RabbitMQ é um message broker. Ele recebe mensagens, organiza‑as em filas e garante que consumidores possam acessá‑las com segurança. RabbitMQ implementa o protocolo AMQP, que define regras claras para envio, roteamento e entrega de mensagens.

O RabbitMQ se destaca pela simplicidade, estabilidade e pela facilidade de adaptação a diferentes cenários — desde pequenas aplicações até sistemas de alta disponibilidade. Dentre alternativas conhecidas estão Kafka, Redis Streams e SQS.

Conceitos básicos

  • Produtor (Producer) – quem envia a mensagem
  • Consumidor (Consumer) – quem lê e processa a mensagem
  • Exchange – recebe a mensagem e a redireciona
  • Fila (Queue) – onde a mensagem fica armazenada
  • Binding – associação entre uma exchange e uma fila
  • Routing key – chave usada para auxiliar no roteamento

O Exchange é a entidade na qual o produtor publica mensagens, que são então roteadas para um conjunto de filas. O tipo de exchange e as propriedades do binding determinam a lógica de roteamento.

Uma Fila no RabbitMQ é uma coleção ordenada de mensagens. As mensagens são enfileiradas (criadas pelo produtor) e desenfileiradas (entregues aos consumidores) de maneira FIFO (“primeiro a entrar, primeiro a sair”).

Exemplo 1 – Conectando ao RabbitMQ com Go

Nota: Este exemplo assume que você já tem Go e RabbitMQ instalados. Consulte a documentação oficial para instruções de instalação.

  • RabbitMQ:
  • Go:

Crie um módulo Go:

go mod init exemplo/mensageria

Em seguida, crie um arquivo main.go (ou teste.go) com o código abaixo, que abre uma conexão com o RabbitMQ e verifica se está funcionando:

package main

import (
    "log"

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

func main() {
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    if err != nil {
        log.Fatalf("Erro ao conectar: %s", err)
    }
    defer conn.Close()

    log.Println("Conexão bem-sucedida com RabbitMQ!")
}

Instale as dependências e execute:

go get
go run .

Se o serviço RabbitMQ estiver em execução, você verá a mensagem de sucesso no log.

Dica: Ajuste a URL de conexão (amqp://guest:guest@localhost:5672/) conforme as credenciais e host que você configurou.

Exemplo 2 – Produção e Consumo de uma Mensagem

Neste exemplo criamos duas aplicações independentes: um produtor que envia mensagens para uma fila e um consumidor que lê essas mensagens.

Estrutura dos projetos

# Pasta do produtor
go mod init exemplo/produtor

# Pasta do consumidor
go mod init exemplo/consumidor

Código do Produtor

package main

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

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

func failOnError(err error, msg string) {
    if err != nil {
        log.Panicf("%s: %s", msg, err)
    }
}

type User struct {
    UserType int    `json:"user_type"`
    Id       int    `json:"id"`
    Name     string `json:"name"`
}

func main() {
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    q, err := ch.QueueDeclare(
        "users", // name
        false,   // durable
        false,   // delete when unused
        false,   // exclusive
        false,   // no-wait
        nil,     // arguments
    )
    failOnError(err, "Failed to declare a queue")

    user := User{UserType: 1, Id: 123, Name: "Alice"}
    body, err := json.Marshal(user)
    failOnError(err, "Failed to marshal JSON")

    err = ch.Publish(
        "",     // exchange
        q.Name, // routing key (queue name)
        false,
        false,
        amqp.Publishing{
            ContentType: "application/json",
            Body:        body,
        })
    failOnError(err, "Failed to publish a message")

    log.Printf(" [x] Sent %s", body)
    time.Sleep(1 * time.Second) // give time for the message to be sent
}

Código do Consumidor

package main

import (
    "log"

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

func failOnError(err error, msg string) {
    if err != nil {
        log.Panicf("%s: %s", msg, err)
    }
}

func main() {
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    msgs, err := ch.Consume(
        "users", // queue
        "",      // consumer
        true,    // auto-ack
        false,   // exclusive
        false,   // no-local
        false,   // no-wait
        nil,     // args
    )
    failOnError(err, "Failed to register a consumer")

    forever := make(chan bool)

    go func() {
        for d := range msgs {
            log.Printf("Received a message: %s", d.Body)
        }
    }()

    log.Printf("Waiting for messages. To exit press CTRL+C")
    <-forever
}

Execute primeiro o consumidor e, em seguida, o produtor. O consumidor exibirá a mensagem recebida no log.

Back to Blog

Related posts

Read more »

Single State Model Architecture

Problem Statement Modern system architectures often prioritize scale and flexibility at the cost of simplicity and consistency. In the rush to adopt microservi...

GO profiling using pprof

What is pprof? pprof is Go's built‑in profiling tool that allows you to collect and analyze runtime data from your application, such as CPU usage, memory alloc...