Spring Boot使用RabbitMQ延时交换机发送消息丢失无异常问题
Spring Boot 向延时交换机投递消息无报错但未到队列的排查方案
- 第一步:确认RabbitMQ延时交换机插件已正确启用
延时交换机(delayed exchange)是RabbitMQ的非内置插件,首先需要登录RabbitMQ管理后台,进入「Exchanges」页,查看Type下拉选项中是否存在x-delayed-message类型,若不存在则说明插件未安装或未启用:- 需下载和你当前RabbitMQ版本完全匹配的
rabbitmq_delayed_message_exchange插件 - 安装后执行
rabbitmq-plugins enable rabbitmq_delayed_message_exchange启用插件,重启RabbitMQ服务后再次验证
- 需下载和你当前RabbitMQ版本完全匹配的
- 第二步:校验延时交换机、队列、绑定关系的声明配置
- 声明交换机时必须指定type为
x-delayed-message,且必须添加参数"x-delayed-type" : "direct/topic/fanout/headers",对应你实际使用的路由类型,示例正确配置:
@Bean public CustomExchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange("delayed_exchange", "x-delayed-message", true, false, args); }- 确认队列和延时交换机的绑定路由键、绑定类型和发送消息时指定的路由键完全匹配,注意topic类型的通配符规则不要写错。
- 声明交换机时必须指定type为
- 第三步:校验消息发送时的延时参数配置
使用convertAndSend发送消息时,必须在消息头中设置x-delay参数,单位为毫秒,错误的参数名或者参数类型都会导致消息不生效,示例正确发送代码:rabbitTemplate.convertAndSend("delayed_exchange", "routing_key", message, msg -> { msg.getMessageProperties().setHeader("x-delay", 5000); // 设置5秒延时 return msg; });- 特别注意:不要把参数名写成
delay或者其他自定义名称,也不要传字符串类型的数值,必须为整数类型。
- 特别注意:不要把参数名写成
- 第四步:开启RabbitMQ消息投递确认机制定位问题
默认情况下Spring Boot RabbitMQ不会开启投递回调,消息发送失败也不会抛出异常,在application.yml中添加以下配置开启回调:
然后给spring: rabbitmq: publisher-confirm-type: correlated publisher-returns: true template: mandatory: trueRabbitTemplate设置ConfirmCallback和ReturnCallback,打印回调结果即可定位问题:- 如果ConfirmCallback返回ack为false,说明消息根本没有到达交换机,排查交换机名称是否写错、RabbitMQ连接账号是否有对应交换机的投递权限
- 如果ConfirmCallback返回ack为true但触发了ReturnCallback,说明消息到达了交换机但没有路由到队列,排查路由键、队列绑定关系是否正确
- 第五步:排查消息是否进入死信队列或被自动丢弃
检查是否给队列设置了x-dead-letter-exchange参数,若投递失败的消息被转发到了死信交换机,可以去对应死信队列查看消息;另外检查消息本身是否设置了比x-delay更短的过期时间(expiration参数),导致消息还没到延时时间就已经过期被丢弃。
内容的提问来源于stack exchange,提问作者Shkelzen
相关产品推荐
相关产品推荐

