0

I'm trying to implement a solution based on a RabbitMQ cluster, composed by 3 nodes, and a HAProxy load balancer which exposes port 1883 in order to receive MQTT connections and redirect them to one of the RabbitMQ nodes following a round robin policy. Then, I wrote two simple Python client, respectively a publisher and a subscriber, using paho mqtt library. I enabled the RabbitMQ MQTT plugin and I created a queue myqueue which is bind with amq.topic exchange by the routing key my/routing/key, that is also the topic on which the two clients send and receive messages.

If I start the publisher, I can see on the RabbitMQ management dashboard that message rates graph goes up, but if I try to get the message from the queue I get Queue is empty pop-up.

Any help ?

  • Please export the definitions from one of your RabbitMQ nodes, and share that file along with the _complete_ source code to your MQTT publisher and subscriber. Ideally I should be able to clone a git repo, import the definitions, and see the same issue you are seeing. If you host your repo on GitHub I can create a PR to assist you. It's very important that the code is _runnable_ because I don't have time to get something working for you! Thanks. – Luke Bakken Mar 10 '23 at 22:04

1 Answers1

0

This is the configuration exported from a RabbitMQ node.

{
  "rabbit_version": "3.8.9",
  "rabbitmq_version": "3.8.9",
  "product_name": "RabbitMQ",
  "product_version": "3.8.9",
  "users": [
    {
      "name": "guest",
      "password_hash": "gkUcvdz4jM11hmZVw9GZkJB3QwqlMefasAtEVPZu1uevVgkY",
      "hashing_algorithm": "rabbit_password_hashing_sha256",
      "tags": "administrator"
    }
  ],
  "vhosts": [{ "name": "/" }],
  "permissions": [
    {
      "user": "guest",
      "vhost": "/",
      "configure": ".*",
      "write": ".*",
      "read": ".*"
    }
  ],
  "topic_permissions": [],
  "parameters": [],
  "global_parameters": [
    { "name": "cluster_name", "value": "rabbit@rabbit1" },
    {
      "name": "internal_cluster_id",
      "value": "rabbitmq-cluster-id-9aELuZUOj0hANyiY-hbyCA"
    }
  ],
  "policies": [],
  "queues": [
    {
      "name": "mqtt-subscription-consumerqos1",
      "vhost": "/",
      "durable": true,
      "auto_delete": false,
      "arguments": { "x-expires": 86400000 }
    },
    {
      "name": "mqtt-subscription-publisherqos1",
      "vhost": "/",
      "durable": true,
      "auto_delete": false,
      "arguments": { "x-expires": 86400000 }
    }
  ],
  "exchanges": [],
  "bindings": [
    {
      "source": "amq.topic",
      "vhost": "/",
      "destination": "mqtt-subscription-consumerqos1",
      "destination_type": "queue",
      "routing_key": "my.routing.key",
      "arguments": {}
    }
  ]
}

This is the source code of publisher and subscriber.

import paho.mqtt.client as mqtt


def on_connect(client, userdata, flag, rc):

    msg = 'Message from publisher!'
    mqtt_topic = 'my/routing/key'

    if(rc == 0):
        print('Client publisher connected successfully\n')

        print('Publisher wants to publish a new message... \n')
        client.publish(mqtt_topic, msg, 1, False)
    elif(rc == 1):
        print('ERROR: Unacceptable protocol version')
    elif(rc == 2):
        print('ERROR: client identifier rejected')
    elif(rc == 3):
        print('ERROR: server unavailable')
    elif(rc == 4):
        print('ERROR: bad username or password')
    elif(rc == 5):
        print('ERROR: not authorized')

    return rc


def on_message(client, userdata, msg):
    print(f'Published message:  {msg.topic} {str(msg.payload)}\n')


if __name__ == "__main__":

    broker = 'localhost'
    port = 1883
    keep_alive = 60

    try:
        # Create a MQTT client object
        client = mqtt.Client('publisher', clean_session=False)

        # Assign callback functions to client object
        client.on_connect = on_connect
        client.on_message = on_message

        # Connect to the MQTT broker
        client.connect(broker, port, keep_alive)

        # Start the loop
        client.loop_forever()

    except Exception as e:
        print(f'Error: {e}')
        client.disconnect()
        print('Client disconnected successfully')
import paho.mqtt.client as mqtt


def on_connect(client, userdata, flag, rc):
    mqtt_topic = 'my/routing/key'

    if(rc == 0):
        print('Client subrscriber connected successfully\n')
        print('Subscriber subscribes itself to a topic ... \n')
        client.subscribe(mqtt_topic, 1)
        print('Waiting for a message from publisher... \n')
        return
    elif(rc == 1):
        print('ERROR: Unacceptable protocol version')
    elif(rc == 2):
        print('ERROR: client identifier rejected')
    elif(rc == 3):
        print('ERROR: server unavailable')
    elif(rc == 4):
        print('ERROR: bad username or password')
    elif(rc == 5):
        print('ERROR: not authorized')

    exit()


def on_message(client, userdata, msg):
    print(f'Received message:  {msg.topic} {str(msg.payload)}\n')


if __name__ == "__main__":

    broker = 'localhost'
    port = 1883
    keep_alive = 60

    try:
        # Create a MQTT client object
        client = mqtt.Client('consumer', clean_session=False)

        # Assign callback functions to client object
        client.on_connect = on_connect
        client.on_message = on_message

        # Connect to the MQTT broker
        client.connect(broker, port, keep_alive)

        # Start the MQTT client loop
        client.loop_forever()

    except Exception as e:
        print(f'Error: {e}')
        client.disconnect()
        print('Client disconnected successfully')

Now I'm able to publish a message and see it on the queue but only if I use the default queue which on RabbitMQ MTT plugin takes a name as mqtt-subscription-. If I define a custom queue, messages apparently are not stored inside it.