当mandatory=true且消息无法路由时,RabbitMQ将消息退回生产者,Spring AMQP通过ReturnCallback捕获该事件,需配合ConfirmCallback实现完整投递链路监控。

在 RabbitMQ 中,当生产者发送消息到 Exchange,但没有匹配到任何绑定的 Queue(比如路由键不匹配、队列不存在或未绑定),且消息设置了 mandatory = true 时,RabbitMQ 会将消息退回给生产者。此时可通过 ReturnListener(现推荐使用 ConfirmCallback + ReturnCallback 组合)来捕获这类“被退回”的消息。
启用 mandatory 并注册 ReturnCallback
ReturnCallback 是 Spring AMQP 中处理 mandatory 退信的核心机制。它只在消息因路由失败被 Broker 主动退回时触发,不是所有失败都走这里(比如连接断开、Broker 不可用等走 ConfirmCallback 的 nack)。
- 必须在发送时设置
messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT)非必需,但建议;关键是要设messageProperties.setMandatory(true) - 通过
RabbitTemplate.setReturnCallback()注册回调,该回调会在消息被退回时被调用 - 注意:
ReturnCallback是 Spring 提供的抽象,底层依赖 AMQP 协议的basic.return方法,需 Broker 支持(默认开启)
ReturnCallback 的典型用法
实现 ReturnCallback 接口,重写 returnedMessage 方法,可获取退回原因、响应码、响应文本、交换器名、路由键等信息:
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
String msgBody = new String(message.getBody(), StandardCharsets.UTF_8);
System.err.println("消息被退回:body=" + msgBody
+ ", replyCode=" + replyCode
+ ", replyText=" + replyText
+ ", exchange=" + exchange
+ ", routingKey=" + routingKey);
// 可记录日志、存库、重发、告警等
});
常见 replyCode 示例:312(NO_ROUTE)、313(NO_CONSUMERS),replyText 通常是 "No route to queue" 或 "No consumers for queue"。
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
立即学习“Java免费学习笔记(深入)”;
配合 ConfirmCallback 确保整体可靠性
ReturnCallback 只管“退信”,不保证消息是否成功到达 Broker。要完整监控投递链路,还需启用发布确认:
- 配置
spring.rabbitmq.publisher-confirm-type: correlated(推荐) - 设置
rabbitTemplate.setConfirmCallback()处理 ack/nack - 只有在 confirm 回调返回 ack 后,才可能触发 return 回调(即消息已抵达 Broker 并被判定无法路由)
- 若 confirm 是 nack(如网络中断、Broker 拒绝),则不会进入 return 流程
验证场景与注意事项
测试 mandatory 退信需构造明确的不可达条件:
- 向一个 direct exchange 发送消息,但 routingKey 与所有绑定队列都不匹配
- 向一个 topic exchange 发送消息,routingKey 完全不满足任何 binding pattern
- Exchange 存在但未绑定任何 Queue(空 Exchange)
- 确保消费者端没有 auto-delete 队列干扰测试(建议手动声明队列并持久化)
注意:mandatory=false 时,不匹配的消息会被静默丢弃,不会触发 ReturnCallback;mandatory=true 才可能退回。

















