Mastering RabbitMQ Delayed and Priority Queues with Spring Boot
This guide explains how to implement delayed and priority queues in RabbitMQ 3.8 using Spring Boot 2.6, covering dead‑letter exchange configuration, message expiration, priority settings, code examples for sending and consuming messages, and practical considerations such as priority limits and ordering behavior.
Environment
Spring Boot 2.6.12 + RabbitMQ 3.8.12 + Erlang 23.2.5
1. Delayed Queue
A delayed queue means a message becomes visible to consumers only after a specified time.
Implementation uses a dead‑letter exchange (DLX):
Create a regular exchange and queue (e.g., simple.exchange , simple.queue ) and set the x-dead-letter-exchange argument to point to the DLX.
Create the dead‑letter exchange and queue (e.g., dlx.exchange , dlx.queue ).
When sending a message, set its TTL (expiration). Once the TTL expires, the broker forwards the message to the DLX.
Messages are dead‑lettered when:
The message is rejected with requeue=false .
The message expires (TTL exceeded).
The queue reaches its maximum length.
Code to send a delayed message:
<code>@Resource
private RabbitTemplate rabbitTemplate;
public Object testSender() {
this.rabbitTemplate.convertAndSend(
"simple.direct",
"",
"Delayed message - " + System.currentTimeMillis(),
message -> {
// set TTL to 10 seconds
message.getMessageProperties().setExpiration("10000");
return message;
});
logger.info(">>>>>>>>> Message sent successfully");
return "success";
}
</code>Listener for the dead‑letter queue:
<code>@RabbitListener(queues = {"dlx.queue"})
public void dlxMessage(String message, Message msg, Channel channel) throws IOException {
try {
System.out.println(new String(msg.getBody()));
logger.info(">>>>>>>>> Received message - {}, messageId: {}", message, msg.getMessageProperties().getMessageId());
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
logger.error("Message receive exception: {}", e.getMessage());
channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, false);
}
}
</code>Key points for delayed queues:
Configure the queue with a dead‑letter exchange.
Set a TTL (expiration) on each message.
2. Priority Queue
Priority queues are supported from RabbitMQ 3.5.0 onward.
Set the queue’s maximum priority with the x-max-priority argument (value 1‑255, typically 1‑10 for efficiency).
Create a direct exchange (e.g., priority-exchange ) and bind a queue (e.g., priority-queue ) to it.
Set x-max-priority to 100 (maximum allowed is 255). Higher values increase Erlang process usage and may affect scheduling.
Sending messages with a specific priority:
<code>@GetMapping("/sendPriority")
public Object sendPriority(String msg, Integer priority) {
ms.sendPriorityQueue(msg, priority);
return "success";
}
public void sendPriorityQueue(String msg, Integer priority) {
logger.info("Preparing to send message: {}", msg);
Message message = MessageBuilder.withBody(msg.getBytes())
.setPriority(priority)
.build();
rabbitTemplate.convertAndSend("priority-exchange", "pe.msg", message);
}
</code>Example messages:
<code>// Message 1
msg=First message&priority=2
// Message 2
msg=Second message&priority=10
// Message 3
msg=Third message&priority=1
// Message 4
msg=Fourth message&priority=7
</code>Listener for the priority queue:
<code>@RabbitListener(queues = {"priority-queue"})
@RabbitHandler
public void listenerPriority(Message message, Channel channel) {
String content = new String(message.getBody(), Charset.forName("UTF-8"));
MessageProperties props = message.getMessageProperties();
try {
System.out.println("Received from exchange: " + props.getReceivedExchange() + ", queue: " + props.getConsumerQueue() + ": " + content);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
} catch (Exception e) {
e.printStackTrace();
try {
channel.basicReject(props.getDeliveryTag(), false);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
</code>When the service runs, messages are consumed in the order of their priority (higher priority first). If a message’s priority exceeds the queue’s maximum, RabbitMQ treats it as having the maximum priority. Testing with priorities above 100 or 255 resulted in unordered delivery.
Messages without a priority property are treated as if their priority were 0. Messages with a priority higher than the queue's maximum are treated as if they were published with the maximum priority.
End of tutorial.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.