RabbitMQ使用以及优化

RabbitMQ使用以及优化

背景说明

项目中需要异步回调客户(具体实现参考rabbitmq死信),客户端收到回调需返回字符串success,否则,会采用梯度回调:分别于0,5,10,30,60分钟后进行回调,5次回调未返回success,记录回调失败;

问题描述

  • rabbitmq延迟队列中消息已经过期,却未路由分发到指定队列。

  • 举例说明:

消息1 过期时间一小时,先进入延迟队列;

消息2 过期时间五分钟,后进入延迟队列;

五分钟后,消息2过期了,消息1 没有过期,消息2不会被路由到指定队列

分析

  • 原因:rabbitmq延迟队列中消息被路由到指定队列需满足两个条件:

    • 已经过期
    • 消息位于延迟队列头部

解决

  • 官方相关说明

Messages which should expire will still only expire from the head of the queue. This means that unlike with normal queues, even per-queue TTL can lead to expired lower-priority messages getting stuck behind non-expired higher priority ones. These messages will never be delivered, but they will appear in queue statistics.

Queues which have a max-length set will, as usual, drop messages from the head of the queue to enforce the limit. This means that higher priority messages might be dropped to make way for lower priority ones, which might not be what you would expect.

看到官网文档说明之后,消息是有优先级的,我就设想:针对不同过期时间消息,进行消息优先级设置(数字越大,优先级越高,亲测可行),于是就按照此方案进行修改代码。修改完成测试发现,结果和预期不一致。

经研究发现,对延迟队列(或者叫死信)中的消息设置优先级是不起作用的,延迟队列中的消息想被路由到指定队列,一是需要到达过期时间,而是需要在队列的头部,这样才能被扫描到,单纯设置消息优先级,是不可行的。

于是,我又想到了其他方案,放入延迟队列的消息,过期时间统一设置5分钟,针对10,30,60分钟过期时间的消息,可以增加消息的轮询次数,未达到指定轮询次数的消息,过期之后继续放入延迟队列,这样就达到了期望的目的。

核心思想

  • 对延迟队列中的消息设置消息优先级是不起作用的。
  • 可以通过消息回调次数 + 消息轮询次数达到梯度回调客户的目的。

你可能感兴趣的:(RabbitMQ)