我正在寻找有关奇怪问题的帮助,其中队列上的慢消费者导致同一队列中的所有其他消费者以30秒的间隔开始消费消息。这是所有消费者,但速度慢的消费者并没有尽可能快地消费消息,而是在消费之前等待一些神奇的30秒屏障。
我的应用程序的基本流程如下:
我对可能导致此问题的原因感到茫然,或者如何修复它,请帮忙。
更多背景和调查结果
expireMessagesPeriod
时间只是以某种方式唤醒amq,然后它会向非慢速消费者发送消息。答案 0 :(得分:4)
虽然不是问题的严格解决方案,但进一步的调查已经揭示了这个问题的根本原因。
TL; DR - 这是已知的行为,在Apollo
之前不会修复更多详情
最终这是由maxPageSize
属性以及AMQ仅将选择条件应用于内存中的消息引起的。通常这些是消息选择器(property = value
),但在我的情况下,它们是JMSXGroupID=>Consumer
分配。
当队列收到消息时,它们会被分页到内存中并放入一个集合(源代码中名为pagedInPendingDispatch
)。要发送消息,AMQ将扫描此消息列表并尝试查找将接受它的消费者。这包括检查组ID,消息选择器和预取缓冲区空间。对于我们的用例,我们不使用消息选择器,但我们正在使用组。如果没有消费者可以接收消息,那么它将留在集合中,并在下一个时间点再次检查。
为了阻止pagedInPendingDispatch
集合占用所有可用资源,建议限制通过maxPageSize
属性配置的此队列的大小。这个属性实际上并不是最大值,它更像是一个提示,在正常情况下,是否应该在内存中分页新邮件或将其分页到磁盘。
有了这两条信息和一个缓慢的消费者,事实证明最终pagedInPendingDispatch
集合中的所有消息最终只能被慢消费者消费,因此集合被有效地阻止而没有其他消息派遣。这解释了为什么慢速消费者不受30秒间隔的影响,它已经有maxPageSize
条消息等待递送。
这并不能解释为什么我看到非慢速消费者每30秒收到一次消息。事实证明,将消息分页到内存有两种模式,普通和强制。正常遵循上面概述的过程,其中集合的大小与maxPageSize
属性进行比较,强制时,但是,消息始终被分页到内存中。此模式用于允许您浏览不在内存中的消息。在发生这种情况时,到期机制也会使用强制模式,以允许AMQ使不在内存中的消息过期。
所以我们现在拥有的是内存中的一组消息,这些消息都是针对发送给同一个消费者的消费者,消费者由于速度慢或被阻止而不接受消费者。我们还有积压的消息等待交付给所有消费者。每隔expireMessagesPeriod
毫秒执行一个任务,强制将消息分页到内存中,以检查它们是否应该过期。这会将这些消息添加到集合中的页面上,这些消息现在包含maxPageSize
消息,用于缓慢消费者和N
个消息,这些消息将发往任何消费者。这些消息将被传递。
QED。
<强>参考强>