RabbitMQ

Detailed documentation on the RabbitMQ pubsub component

Component format

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Component
  3. metadata:
  4. name: rabbitmq-pubsub
  5. spec:
  6. type: pubsub.rabbitmq
  7. version: v1
  8. metadata:
  9. - name: connectionString
  10. value: "amqp://localhost:5672"
  11. - name: protocol
  12. value: amqp
  13. - name: hostname
  14. value: localhost
  15. - name: username
  16. value: username
  17. - name: password
  18. value: password
  19. - name: consumerID
  20. value: myapp
  21. - name: durable
  22. value: false
  23. - name: deletedWhenUnused
  24. value: false
  25. - name: autoAck
  26. value: false
  27. - name: deliveryMode
  28. value: 0
  29. - name: requeueInFailure
  30. value: false
  31. - name: prefetchCount
  32. value: 0
  33. - name: reconnectWait
  34. value: 0
  35. - name: concurrencyMode
  36. value: parallel
  37. - name: publisherConfirm
  38. value: false
  39. - name: enableDeadLetter # Optional enable dead Letter or not
  40. value: true
  41. - name: maxLen # Optional max message count in a queue
  42. value: 3000
  43. - name: maxLenBytes # Optional maximum length in bytes of a queue.
  44. value: 10485760
  45. - name: exchangeKind
  46. value: fanout

Warning

The above example uses secrets as plain strings. It is recommended to use a secret store for the secrets as described here.

Spec metadata fields

FieldRequiredDetailsExample
connectionStringYThe RabbitMQ connection string. Mutally exclusive with protocol, hostname, username, password fieldamqp://user:pass@localhost:5672
protocolNThe RabbitMQ protocol. Mutally exclusive with connectionString fieldamqp
hostnameNThe RabbitMQ hostname. Mutally exclusive with connectionString fieldlocalhost
usernameNThe RabbitMQ username. Mutally exclusive with connectionString fieldusername
passwordNThe RabbitMQ password. Mutally exclusive with connectionString fieldpassword
consumerIDNConsumer ID a.k.a consumer tag organizes one or more consumers into a group. Consumers with the same consumer ID work as one virtual consumer, i.e. a message is processed only once by one of the consumers in the group. If the consumer ID is not set, the dapr runtime will set it to the dapr application ID.
durableNWhether or not to use durable queues. Defaults to “false”“true”, “false”
deletedWhenUnusedNWhether or not the queue should be configured to auto-delete Defaults to “true”“true”, “false”
autoAckNWhether or not the queue consumer should auto-ack messages. Defaults to “false”“true”, “false”
deliveryModeNPersistence mode when publishing messages. Defaults to “0”. RabbitMQ treats “2” as persistent, all other numbers as non-persistent“0”, “2”
requeueInFailureNWhether or not to requeue when sending a negative acknowledgement in case of a failure. Defaults to “false”“true”, “false”
prefetchCountNNumber of messages to prefetch. Consider changing this to a non-zero value for production environments. Defaults to “0”, which means that all available messages will be pre-fetched.“2”
publisherConfirmNIf enabled, client waits for publisher confirms after publishing a message. Defaults to “false”“true”, “false”
reconnectWaitNHow long to wait (in seconds) before reconnecting if a connection failure occurs“0”
concurrencyModeNparallel is the default, and allows processing multiple messages in parallel (limited by the app-max-concurrency annotation, if configured). Set to single to disable parallel processing. In most situations there’s no reason to change this.parallel, single
enableDeadLetterNEnable forwarding Messages that cannot be handled to a dead-letter topic. Defaults to “false”“true”, “false”
maxLenNThe maximum number of messages of a queue and its dead letter queue (if dead letter enabled). If both maxLen and maxLenBytes are set then both will apply; whichever limit is hit first will be enforced. Defaults to no limit.“1000”
maxLenBytesNMaximum length in bytes of a queue and its dead letter queue (if dead letter enabled). If both maxLen and maxLenBytes are set then both will apply; whichever limit is hit first will be enforced. Defaults to no limit.“1048576”
exchangeKindNExchange kind of the rabbitmq exchange. Defaults to “fanout”.“fanout”,“topic”
caCertRequired for using TLSInput/OutputCertificate Authority (CA) certificate in PEM format for verifying server TLS certificates.
clientCertRequired for using TLSInput/OutputTLS client certificate in PEM format. Must be used with clientKey.
clientKeyRequired for using TLSInput/OutputTLS client key in PEM format. Must be used with clientCert. Can be secretKeyRef to use a secret reference.

Communication using TLS

To configure communication using TLS, ensure that the RabbitMQ nodes have TLS enabled and provide the caCert, clientCert, clientKey metadata in the component configuration. For example:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Component
  3. metadata:
  4. name: rabbitmq-pubsub
  5. spec:
  6. type: pubsub.rabbitmq
  7. version: v1
  8. metadata:
  9. - name: host
  10. value: "amqps://localhost:5671"
  11. - name: consumerID
  12. value: myapp
  13. - name: durable
  14. value: false
  15. - name: deletedWhenUnused
  16. value: false
  17. - name: autoAck
  18. value: false
  19. - name: deliveryMode
  20. value: 0
  21. - name: requeueInFailure
  22. value: false
  23. - name: prefetchCount
  24. value: 0
  25. - name: reconnectWait
  26. value: 0
  27. - name: concurrencyMode
  28. value: parallel
  29. - name: publisherConfirm
  30. value: false
  31. - name: enableDeadLetter # Optional enable dead Letter or not
  32. value: true
  33. - name: maxLen # Optional max message count in a queue
  34. value: 3000
  35. - name: maxLenBytes # Optional maximum length in bytes of a queue.
  36. value: 10485760
  37. - name: exchangeKind
  38. value: fanout
  39. - name: caCert
  40. value: ${{ myLoadedCACert }}
  41. - name: clientCert
  42. value: ${{ myLoadedClientCert }}
  43. - name: clientKey
  44. secretKeyRef:
  45. name: myRabbitMQClientKey
  46. key: myRabbitMQClientKey

Note that while the caCert and clientCert values may not be secrets, they can be referenced from a Dapr secret store as well for convenience.

Enabling message delivery retries

The RabbitMQ pub/sub component has no built-in support for retry strategies. This means that the sidecar sends a message to the service only once. When the service returns a result, the message will be marked as consumed regardless of whether it was processed correctly or not. Note that this is common among all Dapr PubSub components and not just RabbitMQ. Dapr can try redelivering a message a second time, when autoAck is set to false and requeueInFailure is set to true.

To make Dapr use more sophisticated retry policies, you can apply a retry resiliency policy to the RabbitMQ pub/sub component.

There is a crucial difference between the two ways to retry messages:

  1. When using autoAck = false and requeueInFailure = true, RabbitMQ is the one responsible for re-delivering messages and any subscriber can get the redelivered message. If you have more than one instance of your consumer, then it’s possible that another consumer will get it. This is usually the better approach because if there’s a transient failure, it’s more likely that a different worker will be in a better position to successfully process the message.
  2. Using Resiliency makes the same Dapr sidecar retry redelivering the messages. So it will be the same Dapr sidecar and the same app receiving the same message.

Create a RabbitMQ server

You can run a RabbitMQ server locally using Docker:

  1. docker run -d --hostname my-rabbit --name some-rabbit rabbitmq:3

You can then interact with the server using the client port: localhost:5672.

The easiest way to install RabbitMQ on Kubernetes is by using the Helm chart:

  1. helm install rabbitmq stable/rabbitmq

Look at the chart output and get the username and password.

This will install RabbitMQ into the default namespace. To interact with RabbitMQ, find the service with: kubectl get svc rabbitmq.

For example, if installing using the example above, the RabbitMQ server client address would be:

rabbitmq.default.svc.cluster.local:5672

Use topic exchange to route messages

Setting exchangeKind to "topic" uses the topic exchanges, which are commonly used for the multicast routing of messages. Messages with a routing key will be routed to one or many queues based on the routing key defined in the metadata when subscribing. The routing key is defined by the routingKey metadata. For example, if an app is configured with a routing key keyA:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Subscription
  3. metadata:
  4. name: order_pub_sub
  5. spec:
  6. topic: B
  7. route: /B
  8. pubsubname: pubsub
  9. metadata:
  10. routingKey: keyA

It will receive messages with routing key keyA, and messages with other routing keys are not received.

  1. // publish messages with routing key `keyA`, and these will be received by the above example.
  2. client.PublishEvent(context.Background(), "pubsub", "B", []byte("this is a message"), dapr.PublishEventWithMetadata(map[string]string{"routingKey": "keyA"}))
  3. // publish messages with routing key `keyB`, and these will not be received by the above example.
  4. client.PublishEvent(context.Background(), "pubsub", "B", []byte("this is another message"), dapr.PublishEventWithMetadata(map[string]string{"routingKey": "keyB"}))

Bind multiple routingKey

Multiple routing keys can be separated by commas.
The example below binds three routingKey: keyA, keyB, and "". Note the binding method of empty keys.

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Subscription
  3. metadata:
  4. name: order_pub_sub
  5. spec:
  6. topic: B
  7. route: /B
  8. pubsubname: pubsub
  9. metadata:
  10. routingKey: keyA,keyB,

For more information see rabbitmq exchanges.

Last modified February 21, 2023: fixed rabbitmq docs for pubsub (#3182) (5c866096)