RabbitMQ Spring Boot #04-Queue configuration

Aleksander Kołata
6 min readOct 29, 2021

--

Hello ! In this article I’m going to cover Rabbit MQ queue configuration options. Let’s jump right into the topic !

Queue basics

In RabbitMQ queue is a data structure with 2 primary operations. Item in the queue can be:

  • enqueued - added at the queue tail
  • dequeued - consumed from the queue head

By default queues in RabbitMQ are FIFO - First In First Out, however there is also a priority queue implementation available.

Queue creation in RabbitMQ management interface

In the previous article RabbitMQ Spring Boot #03 — Exchange configuration I explained how to set up RabbitMQ using Docker. Check it out, if You don’t have it configured yet.

Go to the RabbitMQ management interface http://localhost:15672/ , log in asguest/guest and go to the Queues tab. At the bottom of the page You can create a new queue:

Queue creation using RabbitMQ management interface

As You can see, there is a lot of configuration options to choose from - let’s try to understand them !

Type

  • Classic - non-replicated queue type by default. If You need classic queue replication, You can enable mirroring, but classic queues mirroring is going to be removed in the future RabbitMQ version. Official recommendation is to switch to quorum/stream queue types, if replication is needed
  • Quorum (available since RabbitMQ 3.8.0) - it is a replicated queue to provide high availability and data safety. This type aims to resolve both the performance and the synchronisation failings of mirrored queues. Each quorum queue is a replicated queue - it has a leader and multiple followers. Publishers and consumers always interact with the leader. Quorum queues are both safer and achieve higher throughput than mirrored queues. Quorum queues should be the default choice for a replicated queue type. Documentation can be found here
  • Stream (available since RabbitMQ 3.9.0) is a persistent and replicated data structure, in append-only log model. This is a special type enabled by the Stream Plugin , developed for a specific use cases - here You can read more about it

Name

Queue name - up to 255 bytes of UTF-8 characters. Names starting with amqp. are reserved for the broker.

Durability

Metadata of durable queue is stored on disk, when metadata of transient queue is stored in memory if possible. Transient queue will not survive broker restart. Important takeaway from the documentation:

Durable queues will be recovered on node boot, including messages in them published as persistent. Messages published as transient will be discarded during recovery, even if they were stored in durable queues.

Auto delete

If yes, the queue will delete itself after at least one consumer has connected, and then all consumers have disconnected.

Arguments

RabbitMQ suggests different arguments based on the selected queue type.

  • Message TLL (time-to-live) - time in milliseconds after which message will be discarded from the queue, if it haven’t been consumed yet. Argument name is x-message-ttl
  • Auto expire - time in milliseconds after which the queue will be automatically deleted, if it was unused. Argument name is x-expires
  • Overflow behaviour - determines what happens to messages when the maximum length of a queue is reached. You can find available values in the docs. Argument name is x-overflow
  • Single active consumer - if set, only one active consumer at a time consumes from the queue. Argument name is x-single-active-consumer
  • Dead letter exchange - an exchange for routing dead messages out of the queue because they have reached the end of their time-to-live, they exceed the max length (messages or bytes) configured for the queue, or they have been rejected by the queue or nacked (negative acknowledgement) by the consumer. Argument name is x-dead-letter-exchange
  • Dead letter routing key - optional routing key set when a message is dead-lettered. If not provided, original routing key will be used. Argument name is x-dead-letter-routing-key
  • Max length - defines how many messages the queue is allowed to hold. Messages from the front of the queue will be dead-lettered to make way for new messages when the maximum length is reached. Argument name is x-max-length
  • Max length bytes - defines (in bytes) how large the queue can become. It’s just like the maximum length above, messages from the front of the queue will be dead-lettered first. Argument name is x-max-length-bytes
  • Maximum priority - allows the queue to support message priorities up to some maximum level you set. Argument name is x-max-priority
  • Lazy mode - lazy queues are able to support long queues, containing millions of messages. They writes messages to disc immediately , and messages are loaded into memory only when needed. Argument name is x-queue-mode set to lazy
  • Master locator - set’s the queue into leader locator mode. It is used for classic queues mirroring, argument name is x-queue-master-locator
  • Delivery limit - the number of allowed unsuccessful delivery attempts. If a threshold was reached, message will be dropped or dead-lettered. It is used for quorum queues, argument name is x-delivery-limit
  • Max in memory length - how many (ready) messages a quorum queue can contain in memory before it starts storing them on disk only. It is used for quorum queues, argument name is x-max-in-memory-length
  • Max in memory bytes - same as above, but it is the total size in bytes. It is used for quorum queues, argument name is x-max-in-memory-bytes
  • Initial cluster size - number of quorum queue members, argument name is x-quorum-initial-group-size
  • Max time retention - sets the data retention for stream queues in time units (can be years !). Argument name is x-max-age
  • Max segment size in bytes - stream segment size on disk. Argument name is x-stream-max-segment-size-bytes
  • Initial cluster size - initial stream cluster size, argument name is x-initial-cluster-size
  • Leader locator - stream queue leader locator mode. Argument name is x-queue-leader-locator

Spring Boot queue configuration

Queue declaration using Java configuration

Declaring a queue from Spring configuration is quite easy. Class org.springframework.amqp.core.Queue has following constructors available:

  • Queue(String name)
  • Queue(String name, boolean durable)
  • Queue(String name, boolean durable, boolean exclusive)
  • Queue(String name, boolean durable, boolean exclusive, boolean autoDelete)
  • Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

What these arguments mean?

  • name - queue name. If set to empty string "", then broker will generate the name
  • durable - if true, then queue will survive broker restart
  • auto-delete - if true, broker will delete queue when it is no longer in use
  • exclusive - if true, then this queue will be used only by the declarer’s connection
  • arguments - optional queue’s arguments, described above

After Queue object is initialized, You have few set... methods available:

Example:

@Configuration
public class RabbitMqConfig {

@Bean
public Declarables declarables() {
Queue classicQueue = new Queue("q.classic-demo", false, false, false, Map.of(
"x-queue-mode", "lazy"
));
Queue quorumQueue = new Queue("q.quorum-demo", true, false, false, Map.of(
"x-queue-type", "quorum"
));
Queue streamQueue = new Queue("q.stream-demo", true, false, false, Map.of(
"x-queue-type", "stream"
));
return new Declarables(
classicQueue,
quorumQueue,
streamQueue
);
}

}

If You want to create a queue of type quorum or stream, You can pass x-queue-type argument.

You can also declare a queue using @RabbitListener annotation.

As You can see, declared queues are present in RabbitMQ management interface.

Sources:

--

--

Aleksander Kołata

Senior Full Stack Developer — Java (Spring) and TypeScript (Angular). DDD and software architecture enthusiast.