我有一种情况,我有一个带有 2 个队列 Q1 和 Q2 的 activemq 代理。我有两个使用 activemessaging 的基于 ruby 的消费者。我们称它们为 C1 和 C2。两个消费者都订阅每个队列。我在订阅每个队列时设置了 activemq.prefetchSize=1。我也在设置 ack=client.
考虑以下事件序列:
1) 触发长时间运行作业的消息发布到队列 Q1。称它为 M1。
2) M1 被分派给消费者 C1,开始一个长操作。
3) 两条触发短作业的消息发布到队列 Q2。将这些称为 M2 和 M3。
4) M2 被派往 C2,C2 快速运行短作业。
5) M3 被分派到 C1,即使 C1 仍在运行 M1。它能够分派到 C1,因为 prefetchSize=1 是在队列订阅上设置的,而不是在连接上。因此,已经发送了 Q1 消息这一事实并不能阻止发送 Q2 消息。
由于 activemessaging 消费者是单线程的,因此最终结果是 M3 在 C1 上等待很长时间,直到 C1 完成对 M1 的处理。因此,尽管消费者 C2 处于空闲状态(因为它很快以消息 M2 结束),但 M3 没有长时间处理。
本质上,每当运行一个长 Q1 作业然后创建一大堆短 Q2 作业时,恰好有一个短 Q2 作业卡在等待长 Q1 作业完成的消费者身上。
有没有办法在连接级别而不是订阅级别设置 prefetchSize?我真的不希望在处理 M1 时将任何消息发送到 C1。另一种选择是我可以创建一个专用于处理 Q1 的消费者,然后让其他消费者专用于处理 Q2。但是,我宁愿不这样做,因为 Q1 消息很少——Q1 的专用消费者会在一天中的大部分时间处于空闲状态,占用内存。