RabbitMQ 通过 Delayed Message Plugin 实现延迟消息,需安装启用插件、声明 x-delayed-message 类型交换机、发送时在 headers 中设置 x-delay(毫秒),Spring Boot 可通过 CustomExchange 和 MessagePostProcessor 简化集成。

RabbitMQ 本身不原生支持延迟消息,但通过官方插件 Delayed Message Plugin(rabbitmq_delayed_message_exchange),可以轻松实现定时/延时投递业务,比如订单超时取消、验证码过期、任务重试等场景。
1. 安装并启用 Delayed Message 插件
该插件从 RabbitMQ 3.6.0 开始支持,3.8+ 版本需手动安装(3.12+ 已内置但默认未启用):
- 查看插件列表:
rabbitmq-plugins list | grep delayed - 启用插件(需重启或运行命令):
rabbitmq-plugins enable rabbitmq_delayed_message_exchange - 确认已启用后,重启 RabbitMQ 或执行
rabbitmqctl stop_app && rabbitmqctl start_app
⚠️ 注意:Docker 部署时需在 docker run 中挂载插件或使用自定义镜像;K8s 环境建议通过 initContainer 安装插件。
2. 声明延迟交换机(Delayed Exchange)
插件提供一种特殊类型交换机:x-delayed-message。Java 客户端需显式声明,并设置参数 x-delayed-type 指定底层路由逻辑(如 direct、topic):
// 声明一个延迟交换机
Map<string object> args = new HashMap();
args.put("x-delayed-type", "direct");
channel.exchangeDeclare("delayed.exchange", "x-delayed-message", true, false, args);
</string>
注意:exchangeDeclare 的类型必须是 "x-delayed-message",不能写错为 "delayed" 或其他值。
3. 发送带延迟的消息
发送时不再用 TTL + 死信链路,而是直接在消息属性中设置 x-delay(单位:毫秒):
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.deliveryMode(2) // 持久化
.contentType("application/json")
.headers(Map.of("x-delay", 60_000)) // 延迟 60 秒
.build();
<p>channel.basicPublish("delayed.exchange", "routing.key", props, messageBodyBytes);
</p>
✅ 关键点:
-
x-delay是 header 字段,不是 message property 的标准字段,必须放在headers中 - Spring AMQP 用户可直接用
MessagePostProcessor设置:message.getMessageProperties().setHeader("x-delay", 30_000); - 延迟时间最大支持约 49 天(
Integer.MAX_VALUE毫秒),超过会静默截断
4. Spring Boot 集成示例(推荐方式)
使用 spring-boot-starter-amqp 可简化配置:
@Configuration
public class RabbitMQConfig {
@Bean
public CustomExchange delayedExchange() {
Map<string object> args = new HashMap();
args.put("x-delayed-type", "topic");
return new CustomExchange("delayed.exchange", "x-delayed-message", true, false, args);
}
<pre class="brush:php;toolbar:false;">@Bean
public Queue delayQueue() {
return QueueBuilder.durable("queue.delayed").build();
}
@Bean
public Binding binding() {
return BindingBuilder.bind(delayQueue()).to(delayedExchange());
}
}
发送时:
public void sendDelayedOrder(String orderId) {
String msg = "{\"orderId\":\"" + orderId + "\",\"status\":\"pending\"}";
Message message = MessageBuilder.withBody(msg.getBytes())
.setHeader("x-delay", 5 * 60_000) // 5 分钟后触发
.build();
rabbitTemplate.convertAndSend("delayed.exchange", "order.cancel", message);
}
消费端只需监听绑定的队列,无需额外处理延迟逻辑 —— 插件会在延迟到期后自动将消息路由过去。
不复杂但容易忽略:插件只影响消息入队时机,不改变消息生命周期管理;务必确保交换机、队列、绑定都正确定义,且消费者已启动并完成预热连接。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










