RabbitMq 死信消息的过期时间的不同 会导致消费延时

业务需求是:消息7天过期。
概述:自测没问题发布了测试版本,为了测试方便将过期时间7天修改为10分钟。但是由于之前跑的测试数据中已经发送过过期时间为7天的消息,导致后续过期时间为10分钟的消息始终无法消费。

处理方式:
前往rabbitmq安装位置sbin 使用rabbtimqctl指令
rabbitmqctl常用命令

#未消费的消息数量
# ./rabbitmqctl list_queues
Listing queues
queue-question-expire   0
queue-question-expire-dl        32
#手动消费消息
# ./rabbitmqctl purge_queue queue-question-expire-dl
Purging queue 'queue-question-expire-dl' in vhost '/'
#手动消费后结果
# ./rabbitmqctl list_queues
Listing queues
queue-question-expire   0
queue-question-expire-dl        0

然后再发送的消息就可以正常消费了。

扩展:
这里其实官方网站有说明的
Doc: rabbitmq-TTL

Caveats
Queues that had a per-message TTL applied to them retroactively (when they already had messages) will discard the messages when specific events occur. Only when expired messages reach the head of a queue will they actually be discarded (or dead-lettered). Consumers will not have expired messages delivered to them. Keep in mind that there can be a natural race condition between message expiration and consumer delivery, e.g. a message can expire after it was written to the socket but before it has reached a consumer.
When setting per-message TTL expired messages can queue up behind non-expired ones until the latter are consumed or expired. Hence resources used by such expired messages will not be freed, and they will be counted in queue statistics (e.g. the number of messages in the queue).
When retroactively applying a per-message TTL policy, it is recommended to have consumers online to make sure the messages are discarded quicker.
Given this behaviour of per-message TTL settings on existing queues, when the need to delete messages to free up resources arises, queue TTL should be used instead (or queue purging, or queue deletion).

引用别人的翻译
https://blog.csdn.net/sinat_36553913/article/details/91351868

注意事项
当队列中已有消息,并设置消息的TTL,那么会追溯设置消息的有效期,当在特定情况下将会丢弃这些消息。只有当过期消息到达队列的头部时,它们才会被真实地丢弃(或死信路由)。消费者将不会接收到过期的消息,但是消息的传递和有效期有天然的竞争关系。比如,一个消息在被写入到socket但还未到达消费者时过期。

当设置了TTL过期时间的消息,可以在未过期消息后面排队,直到后者被消费或者过期。因此,被过期消息使用的资源并不会被释放,它们也会被队列的统计记入(比如,队列中消息的数量)。

当回溯地设置消息的TTL策略时,建议有消费者同时在线,可以保证消息的尽快丢弃。

考虑到给已存在的队列设置消息的TTL,来实现删除消息释放资源。设置队列的TTL(或队列清空,队列删除)应该替代这种方式

测试:
1.可以看出这次是正常发送,正常消费

rabbitMqSender.sendMsg("798", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 1 *1000);
rabbitMqSender.sendMsg("456", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 5 *1000);
rabbitMqSender.sendMsg("123", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 10 *1000);
消息发送时间:2020-07-02T15:03:34.036, 消息内容:798
消息发送时间:2020-07-02T15:03:34.039, 消息内容:456
消息发送时间:2020-07-02T15:03:34.039, 消息内容:123

2020-07-02 15:03:35.116  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:798 
2020-07-02 15:03:39.054  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:456 
2020-07-02 15:03:44.055  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:123 

2.可以看出消息正常发出,但是过了10s同时被消费

rabbitMqSender.sendMsg("123", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 10 *1000);
rabbitMqSender.sendMsg("456", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 5 *1000);
rabbitMqSender.sendMsg("798", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 1 *1000);
2020-07-02 15:05:45.654  INFO 132 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:05:45.654, 消息内容:123
2020-07-02 15:05:45.655  INFO 132 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:05:45.655, 消息内容:456
2020-07-02 15:05:45.655  INFO 132 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:05:45.655, 消息内容:798

2020-07-02 15:05:55.665  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:123 
2020-07-02 15:05:55.666  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:456 
2020-07-02 15:05:55.666  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:798 

3.可以看出过了5秒第一次被消费,再过5秒后后两条消息同时被消费

rabbitMqSender.sendMsg("456", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 5 *1000);
rabbitMqSender.sendMsg("123", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 10 *1000);
rabbitMqSender.sendMsg("798", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 1 *1000);
2020-07-02 15:11:26.929  INFO 11156 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:11:26.929, 消息内容:456
2020-07-02 15:11:26.931  INFO 11156 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:11:26.931, 消息内容:123
2020-07-02 15:11:26.931  INFO 11156 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:11:26.931, 消息内容:798

2020-07-02 15:11:31.928  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:456 
2020-07-02 15:11:36.946  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:123 
2020-07-02 15:11:36.947  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:798 

4.可以看出过了5秒前两条消息同时被消费,再过了5秒最后一条消息被消费

rabbitMqSender.sendMsg("456", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 5 *1000);
rabbitMqSender.sendMsg("798", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 1 *1000);
rabbitMqSender.sendMsg("123", RabbitMqConfig.EXCHANGE_QUESTION_EXPIRE_DL, RabbitMqConfig.ROUTINGKEY_QUESTION_EXPIRE_DL, 10 *1000);
2020-07-02 15:12:27.818  INFO 10400 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:12:27.818, 消息内容:456
2020-07-02 15:12:27.821  INFO 10400 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:12:27.821, 消息内容:798
2020-07-02 15:12:27.821  INFO 10400 --- [           main] com.example.demo.sender.RabbitMqSender   : 消息发送时间:2020-07-02T15:12:27.821, 消息内容:123

2020-07-02 15:12:32.834  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:456 
2020-07-02 15:12:32.834  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:798 
2020-07-02 15:12:37.837  INFO 15856 --- [ntContainer#0-1] c.e.demo.listener.RabbitMqReceiver       : received msg:123 

可以看出应该就是只有消息队列头的消息被消费后,过期的消息才会被消费。不过rabbitmq应该是有一些配置处理这种情况,待处理。

代码已上传git
https://github.com/emws/RabbitmqDemo.git

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值