RabbitMQ: Getting started

How to use Stackhero for RabbitMQ

Let's go through how to connect your Python application to RabbitMQ using the Aio Pika library. In most cases, you simply need to provide the AMQPS URL to establish a secure connection:

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

Below is a complete example demonstrating how to establish a secure connection to RabbitMQ, create a channel, and declare a basic queue. This is an excellent way to verify your configuration:

import asyncio
import logging
import aio_pika

async def main() -> None:
    # If you wish to see debug logs, you can uncomment the following line
    # 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())

If you encounter an error like this when connecting from Python:

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

this usually means your system is missing the Let's Encrypt CA certificate. To resolve this, install the appropriate CA certificates package for your operating system:

  1. On Ubuntu/Debian, run:

    sudo apt install ca-certificates
    
  2. On Alpine Linux, run:

    apk add ca-certificates
    

If you are unable to use these commands, you can also install the CA certificate manually:

  1. Download the Let's Encrypt CA certificate from https://letsencrypt.org/certs/isrgrootx1.pem.

  2. Then, connect to RabbitMQ in your Python code by specifying the CA certificate file:

    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
    )
    

Here is a full example using the Let's Encrypt CA certificate for secure connections:

import asyncio
import logging
import ssl
import aio_pika

async def main() -> None:
    # To enable debug logs, you can uncomment this line
    # logging.basicConfig(level=logging.DEBUG)

    ssl_context = ssl.create_default_context()
    # Load the Let's Encrypt CA certificate you downloaded
    # For example: 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())

To connect a Go application to RabbitMQ, the official Go RabbitMQ Client Library makes the process straightforward. Here’s how to get started:

  1. Create a new directory and initialise your Go module:
go mod init rabbitmq-example
  1. Next, add the RabbitMQ library to your project:
go get github.com/rabbitmq/amqp091-go
  1. Now, create a file named main.go and add the following code:

    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. Run your code with:

go run main.go

If the connection is successful, you will see the message "Successfully connected to RabbitMQ instance". This means you are securely connected with authentication and TLS encryption.

For more advanced examples, refer to the Go examples in the official RabbitMQ repository: https://github.com/rabbitmq/rabbitmq-tutorials/tree/main/go.

If you are developing in PHP, the php-amqplib library allows you to connect to your RabbitMQ instance. As Stackhero uses TLS encryption (SSL), it is recommended to use 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);

In some cases, your TLS connection may require a Certificate Authority (CA) certificate. Many systems already include this, but you can download it manually if needed. Here’s how:

  1. Download the certificate from https://letsencrypt.org/certs/isrgrootx1.pem and save it on your server.
  2. Then, connect using PHP with the downloaded certificate as follows:
$sslOptions = array(
  'cafile' => realpath(__DIR__ . '/isrgrootx1.pem'),
);

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

If you are using Symfony, you can configure it to use RabbitMQ as a message broker by setting the MESSENGER_TRANSPORT_DSN environment variable. Simply update your .env file:

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

Replace <USER>, <PASSWORD>, <HOST>, and <PORT> with your own RabbitMQ details.

Next, ensure your config/packages/messenger.yaml file uses the MESSENGER_TRANSPORT_DSN variable. It should look like this:

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

For Spring Boot applications, configure a secure connection to your Stackhero RabbitMQ instance by updating your application properties:

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

If you are developing with .NET and MassTransit, here’s how to configure your project to connect securely to Stackhero RabbitMQ using TLS encryption:

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();
  }
}

If you are connecting from Elixir and see the error message

CLIENT ALERT: Fatal - Handshake Failure

this generally indicates a bug in the AMQP library’s handling of TLS 1.3. A reliable workaround is to force the use of TLS 1.2 by adding this option when opening the connection:

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

If you see the error Error: Socket closed abruptly during opening handshake when using Node.js, it is likely due to using a version of the amqplib library older than 0.10.7 with RabbitMQ 4.1.0 or later. This change is related to the frame_max setting introduced in RabbitMQ 4.1.0.

To resolve this issue, update your amqplib library to version 0.10.7 or newer.