死信交换机必须显式声明为@bean,否则消息会被静默丢弃;x-dead-letter-routing-key必须显式指定且与binding路由键严格一致;队列参数须用queuebuilder.witharguments()设置,不可用setarguments()。

死信交换机必须显式声明,不能只靠字符串名
很多人以为只要在队列参数里写 x-dead-letter-exchange="DL_EXCHANGE",RabbitMQ 就会自动创建这个交换机——实际不会。如果该交换机未被 Spring Boot 显式声明为 @Bean,启动时不会报错,但消息变成死信后会被静默丢弃(AMQP 协议规定:发往不存在的交换机,消息直接丢弃,无日志、无告警)。
正确做法是:用 ExchangeBuilder 或具体类型构造器(如 DirectExchange、FanoutExchange)声明一个带 @Bean 的交换机实例,并确保名称与队列中配置的 x-dead-letter-exchange 值完全一致(区分大小写、空格、下划线)。
- 必须使用
durable(true),否则重启 RabbitMQ 后死信路由失效 - 不建议用
autoDelete=true,死信交换机需长期存在 - 交换机类型(direct/fanout/topic)不影响死信投递逻辑,但要和绑定死信队列时的
Binding方式匹配
死信路由键(x-dead-letter-routing-key)不填时的行为很危险
当队列声明中没设置 x-dead-letter-routing-key,RabbitMQ 会默认复用原消息的 routingKey。这在多数场景下会导致死信无法到达目标队列——比如你用 normal.queue 接收消息,绑定了 exchange 的 normal.queue key;死信转发时若仍用 normal.queue 作为路由键,而死信交换机只绑定了 dl.key,那消息就丢了。
所以强烈建议显式指定 x-dead-letter-routing-key,且该值必须与后续 Binding 中使用的 routingKey 完全一致:
- 例如队列参数里写
args.put("x-dead-letter-routing-key", "KEY_R") - 则死信交换机绑定死信队列时,
BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with("KEY_R")必须对得上 - 值为空字符串
""或null会导致绑定失败或路由不可预测,不要这么用
队列参数必须在 QueueBuilder.withArguments() 中传入,不能靠 setArguments()
Spring AMQP 的 Queue 构造行为有陷阱:new Queue("name", true) 创建的队列对象,即使后续调用 setArguments(map),这些参数也不会生效——因为 RabbitMQ 只在队列首次声明(declare)时读取参数,而 setArguments() 发生在声明之后。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
唯一可靠的方式是用 QueueBuilder.durable("name").withArguments(args).build()。常见错误写法包括:
-
new Queue("DL_QUEUE", true).setArguments(args)→ 参数无效 - 用
@Queue注解 +arguments属性(如@Queue(name="q", arguments = @Argument(name="x-dead-letter-exchange", value="DLX")))→ 仅适用于简单字符串值,不支持嵌套结构,且易拼错 - 漏掉
.durable(true)→ 非持久化队列在 Broker 重启后消失,参数丢失
死信队列本身不需要声明 x-dead-letter-* 参数
只有「产生死信」的业务队列才需要配置 x-dead-letter-exchange 和 x-dead-letter-routing-key;死信队列(即最终接收死信的队列)就是个普通队列,它不需要、也不应该再配这些参数。
否则会出现“死信的死信”,即死信被二次转发,极难排查。典型症状是:消息进了一次死信队列,又被转到另一个交换机,最后消失在某个未监听的队列里。
验证点很简单:打开 RabbitMQ 管理界面 → 进入队列详情页 → 查看 Arguments 栏。业务队列应含 x-dead-letter-exchange,死信队列的 Arguments 应为空或仅含 TTL / max-length 等非 DLX 相关项。
最容易被忽略的是参数拼写:必须是 x-dead-letter-exchange(不是 dead-letter-exchange 或 X-Dead-Letter-Exchange),大小写和连字符一个都不能错。RabbitMQ 对参数名严格区分,错一个字符就等于没配。










