RabbitMQ: Primeiros passos

Como utilizar o Stackhero para RabbitMQ

Vamos mostrar-lhe como pode ligar a sua aplicação Python ao RabbitMQ utilizando a biblioteca Aio Pika. Na maioria dos casos, só precisa de fornecer o URL AMQPS para estabelecer uma ligação segura:

connection = await aio_pika.connect_robust(
  "amqps://admin:<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>",
)

Segue-se um exemplo completo que demonstra como estabelecer uma ligação segura ao RabbitMQ, criar um canal e declarar uma fila básica. Esta é uma excelente forma de verificar a sua configuração:

import asyncio
import logging
import aio_pika

async def main() -> None:
    # Se quiser ver logs de debug, pode descomentar a linha seguinte
    # logging.basicConfig(level=logging.DEBUG)

    connection = await aio_pika.connect_robust(
        "amqps://admin:<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>"
    )

    async with connection:
        print("The connection worked!")
        channel = await connection.channel()
        await channel.set_qos(prefetch_count=10)
        queue = await channel.declare_queue("test_queue", auto_delete=True)

if __name__ == "__main__":
    asyncio.run(main())

Se encontrar um erro semelhante ao seguinte ao ligar-se a partir do Python:

aiormq.exceptions.AMQPConnectionError: [Errno 5] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1006)

isto normalmente significa que o certificado da autoridade certificadora (CA) Let's Encrypt não está instalado no seu sistema. Para resolver, instale o pacote de certificados CA adequado ao seu sistema operativo:

  1. Em Ubuntu/Debian, execute:

    sudo apt install ca-certificates
    
  2. Em Alpine Linux, execute:

    apk add ca-certificates
    

Se não conseguir utilizar estes comandos, pode sempre instalar o certificado CA manualmente:

  1. Faça o download do certificado CA Let's Encrypt em https://letsencrypt.org/certs/isrgrootx1.pem.

  2. Depois, pode ligar-se ao RabbitMQ no seu código Python especificando o ficheiro do certificado CA:

    import ssl
    
    ssl_context = ssl.create_default_context()
    ssl_context.load_verify_locations(cafile='isrgrootx1.pem')
    
    connection = await aio_pika.connect_robust(
      "amqps://admin:<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>",
      ssl_context=ssl_context
    )
    

Segue um exemplo completo utilizando o certificado CA Let's Encrypt para ligações seguras:

import asyncio
import logging
import ssl
import aio_pika

async def main() -> None:
    # Para ativar logs de debug, pode descomentar esta linha
    # logging.basicConfig(level=logging.DEBUG)

    ssl_context = ssl.create_default_context()
    # Carregue o certificado CA Let's Encrypt que descarregou
    # Por exemplo: wget https://letsencrypt.org/certs/isrgrootx1.pem
    ssl_context.load_verify_locations(cafile='isrgrootx1.pem')

    connection = await aio_pika.connect_robust(
        "amqps://admin:<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>",
        ssl_context=ssl_context
    )

    async with connection:
        print("The connection worked!")
        channel = await connection.channel()
        await channel.set_qos(prefetch_count=10)
        queue = await channel.declare_queue("test_queue", auto_delete=True)

if __name__ == "__main__":
    asyncio.run(main())

Se pretende ligar-se ao RabbitMQ a partir de uma aplicação Go, a Go RabbitMQ Client Library oficial torna o processo simples. Veja como pode começar:

  1. Crie uma nova pasta e inicialize o seu módulo Go:
go mod init rabbitmq-example
  1. Em seguida, adicione a biblioteca RabbitMQ ao seu projeto:
go get github.com/rabbitmq/amqp091-go
  1. Agora, crie um ficheiro chamado main.go e adicione o seguinte código:

    package main
    
    import (
      "fmt"
      amqp "github.com/rabbitmq/amqp091-go"
    )
    
    func main() {
      connection, err := amqp.Dial("amqps://<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>")
      if err != nil {
        panic(err)
      }
      defer connection.Close()
    
      fmt.Println("Successfully connected to RabbitMQ instance")
    }
    
  2. Pode executar o seu código com:

go run main.go

Se a ligação for bem-sucedida, deverá ver a mensagem "Successfully connected to RabbitMQ instance". Isto significa que está ligado de forma segura, com autenticação e encriptação TLS.

Para exemplos mais detalhados, consulte os exemplos Go no repositório oficial do RabbitMQ: https://github.com/rabbitmq/rabbitmq-tutorials/tree/main/go.

Se está a trabalhar com PHP, pode utilizar a biblioteca php-amqplib para se ligar à sua instância RabbitMQ. Como o Stackhero utiliza encriptação TLS (SSL), deve utilizar AMQPSSLConnection:

use PhpAmqpLib\Connection\AMQPSSLConnection;

$connection = new AMQPSSLConnection(
  '<XXXXXX>.stackhero-network.com',
  <AMQP_PORT_TLS>,
  'admin',
  '<PASSWORD>',
  '/',
  array()
);

/**
 * @param \PhpAmqpLib\Connection\AbstractConnection $connection
 */
function shutdown($connection)
{
  $connection->close();
}

register_shutdown_function('shutdown', $connection);

Por vezes, a sua ligação TLS pode necessitar de um certificado de Autoridade Certificadora (CA). Embora muitos sistemas já incluam este certificado, pode descarregá-lo manualmente se necessário. Veja como:

  1. Faça o download do certificado em https://letsencrypt.org/certs/isrgrootx1.pem e guarde-o no seu servidor.
  2. Depois, pode ligar-se em PHP utilizando o certificado descarregado da seguinte forma:
$sslOptions = array(
  'cafile' => realpath(__DIR__ . '/isrgrootx1.pem'),
);

$connection = new AMQPSSLConnection(
  '<XXXXXX>.stackhero-network.com',
  <AMQP_PORT_TLS>,
  'admin',
  '<PASSWORD>',
  '/',
  $sslOptions
);

Se utiliza Symfony, pode configurá-lo para usar o RabbitMQ como message broker, definindo a variável de ambiente MESSENGER_TRANSPORT_DSN. Só precisa de atualizar o seu ficheiro .env:

MESSENGER_TRANSPORT_DSN=amqps://<USER>:<PASSWORD>@<HOST>:<PORT>/%2f/messages?cacert=%2Fetc%2Fssl%2Fcerts%2Fca-certificates.crt

Substitua <USER>, <PASSWORD>, <HOST> e <PORT> pelos seus próprios dados do RabbitMQ.

De seguida, certifique-se de que o seu ficheiro config/packages/messenger.yaml utiliza a variável MESSENGER_TRANSPORT_DSN. Deve ter um aspeto semelhante a este:

framework:
    messenger:
        transports:
            async: '%env(MESSENGER_TRANSPORT_DSN)%'

Para aplicações Spring Boot, pode configurar uma ligação segura à sua instância RabbitMQ Stackhero atualizando as propriedades da aplicação:

spring.rabbitmq.host=<XXXXXX>.stackhero-network.com
spring.rabbitmq.port=<AMQP_PORT_TLS>
spring.rabbitmq.username=admin
spring.rabbitmq.password=<PASSWORD>
spring.rabbitmq.ssl.enabled=true
spring.rabbitmq.ssl.algorithm=TLSv1.2

Se está a desenvolver com .NET e MassTransit, veja como pode configurar o seu projeto para se ligar de forma segura ao Stackhero RabbitMQ utilizando encriptação TLS:

using MassTransit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;

public class Program
{
  public static void Main(string[] args)
  {
    var host = Host.CreateDefaultBuilder(args)
      .ConfigureServices((context, services) =>
      {
        services.AddMassTransit(x =>
        {
          x.UsingRabbitMq((context, cfg) =>
          {
            cfg.Host(new Uri("amqps://admin:<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>"), h =>
            {
              h.UseSsl(s =>
              {
                s.Protocol = System.Security.Authentication.SslProtocols.Tls12;
              });
            });
          });
        });

        services.AddMassTransitHostedService(true);
      })
      .Build();

    host.Run();
  }
}

Se se ligar a partir de Elixir e vir a mensagem de erro

CLIENT ALERT: Fatal - Handshake Failure

isto normalmente indica um bug no suporte da biblioteca AMQP para TLS 1.3. Uma solução fiável é forçar a utilização de TLS 1.2 ao incluir esta opção ao abrir a ligação:

AMQP.Connection.open("amqps://admin:<PASSWORD>@<XXXXXX>.stackhero-network.com:<AMQP_PORT_TLS>", :undefined, ssl_options: [ versions: [ :"tlsv1.2" ] ])

Se vir o erro Error: Socket closed abruptly during opening handshake ao utilizar Node.js, é provável que esteja a usar uma versão da biblioteca amqplib anterior à 0.10.7 com RabbitMQ 4.1.0 ou superior. Esta alteração está relacionada com a configuração frame_max introduzida no RabbitMQ 4.1.0.

Para resolver, atualize a sua biblioteca amqplib para a versão 0.10.7 ou mais recente.