Master RabbitMQ Dead-Letter Queues: When and How Messages Get Redirected
This guide explains RabbitMQ dead-letter queues, detailing the conditions that cause messages to become dead letters, how to configure exchanges and queues with x-dead-letter parameters, and demonstrates three testing methods—reject/nack, TTL expiration, and max-length overflow—using Spring Boot code examples.
Environment
Spring Boot 2.3.10 + RabbitMQ 3.8.12 + Erlang 23.2.5
Dead Letter Queue Introduction
Messages in a queue can become "dead letters" and be republished to an exchange when any of the following events occur:
The consumer calls basic.reject or basic.nack with the requeue parameter set to false .
The message has a TTL (set via x-message-ttl on the queue) and expires, or the queue exceeds its length limit and discards messages.
Note: Queue expiration (set via x-expires) does not cause its messages to become dead letters.
A dead‑letter exchange is a normal exchange and can be of any type.
When creating a queue, you can specify x-dead-letter-exchange and optionally x-dead-letter-routing-key to redirect messages that meet the above conditions.
Prepare Environment
Create the normal business exchange and queue needed for the workflow.
Create a business-exchange of type topic:
Create a dead‑letter exchange named dead-exchange of type fanout:
Create the business queue business-queue and bind it to the exchange, setting x-dead-letter-exchange to the dead‑letter exchange (no routing key needed because the dead‑letter exchange is fanout).
Test
Method 1: Consumer rejects with basic.reject or basic.nack
Send message endpoint:
@GetMapping("/sendDeadLetter")
public Object sendDeadLetter(String msg) {
ms.sendDeadLetter(msg);
return "success";
}
public void sendDeadLetter(String msg) {
logger.info("准备发送消息:{}", msg);
rabbitTemplate.convertAndSend("business-exchange", "be.1", msg);
}Message listener:
@Component
public class MessageListener {
@RabbitListener(queues = { "bussiness-queue" })
@RabbitHandler
public void listener1(Message message, Channel channel) {
System.out.println("接受到消息.....income");
byte[] body = message.getBody();
MessageProperties mps = message.getMessageProperties();
String content = new String(body, Charset.forName("UTF-8"));
try {
// Simulate rejection
if ("1".equals(content)) {
System.out.println("拒绝消息:1");
channel.basicReject(mps.getDeliveryTag(), false);
return;
}
System.out.println("接受到消息来自交换机: 【" + mps.getReceivedExchange() + "】, 队列:【" + mps.getConsumerQueue() + "】:
\t\t内容: " + content);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
} catch (Exception e) {
e.printStackTrace();
try {
channel.basicReject(mps.getDeliveryTag(), false);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}The listener rejects the message when the payload is "1".
Send a normal message:
Send a rejected message (payload "1"):
View the queues – the rejected message appears in the dead‑letter queue.
Method 2: Set message TTL (expiration)
Recreate business-queue with x-message-ttl set to 10000 ms (10 seconds).
Bind the queue to the exchange.
Send a message and wait 10 seconds; the expired message is automatically routed to the dead‑letter queue.
Method 3: Set maximum queue length
Delete the existing bussiness-queue and recreate it with x-max-length=3. Any message beyond the third is sent to the dead‑letter queue.
Send three messages – they stay in the queue. Sending a fourth message causes the oldest message to be moved to the dead‑letter queue.
The overflow message appears in the dead‑letter queue.
These examples demonstrate the situations in which RabbitMQ redirects messages to a dead‑letter queue.
End of tutorial.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
