【问题标题】:How to disable RabbitMQ prefetch count with SimpleMessageListenerContainer如何使用 SimpleMessageListenerContainer 禁用 RabbitMQ 预取计数
【发布时间】:2016-10-12 08:53:04
【问题描述】:

RabbitMQ 提供了选择设置预取计数的能力。

使用 spring-amqp 的 SimpleMessageListenerContainer,我注意到预取计数始终设置。我无法将预取计数设置为 0,因为 SimpleMessageListenerContainer 将其设置为至少 txSize 必须大于零(即使不涉及事务)。那么有没有办法禁用预取计数,即使其无限制?

这里是 spring-amqp 的相关代码:

SimpleMessageListenerContainer.createBlockingQueueConsumer() 这样做:

    int actualPrefetchCount = prefetchCount > txSize ? prefetchCount : txSize;

BlockingQueueConsumer.start() 这样做:

    if (!acknowledgeMode.isAutoAck()) {
        // Set basicQos before calling basicConsume (otherwise if we are not acking the broker
        // will send blocks of 100 messages)
        try {
            channel.basicQos(prefetchCount);
        }

Springs 的BlockingQueueConsumer 中总是调用 basicQos() 的原因是什么?没有禁用预取计数的用例吗? (显然自动确认除外)。

The rabbitmq documentation 讨论了使用通道(全局)范围设置预取计数的开销。没有明确提到使用消费者范围设置它与根本不设置它相比是否有任何开销。如果我没记错的话,spring 总是将它设置为消费者范围。它真的没有任何开销吗?没有选项不设置它似乎仍然很奇怪。

谢谢

【问题讨论】:

    标签: java spring rabbitmq spring-amqp spring-rabbit


    【解决方案1】:

    由于当前实现移交给内部队列,由于早期 rabbitmq 客户端的工作方式,如果消费者跟不上,不设置 qos 将导致 OOM 条件。

    事实上,在 Spring AMQP 的早期版本中,自动确认会发生这种情况,因此队列会根据预取大小进行限制,以阻止代理在这种情况下发送消息。

    在 2.0 中,我们是 planning a new container implementation that avoids this queue,因为兔子客户端不再有需要它的问题。那么我们可以考虑支持qos=0。

    【讨论】:

    • 好的,我明白了。这回答了我的问题。当您说删除内部队列时,您的意思是用rabbitmq客户端的com.rabbitmq.client.QueueingConsumer替换它吗?因为在这种情况下,如果应用程序没有设置 qos 并且无法跟上,您仍然会得到 OOM,对吗?另外,您是否知道在设置预取计数(在消费者级别)实际上是否有任何开销?再次感谢。
    • 再想一想,我不认为你的意思是用 com.rabbitmq.client.QueueingConsumer 替换它,因为那将是等价的。我想你的意思是新的容器实现将直接使用rabbit客户端,这意味着它自己的线程池分发给消费者,它自己的WorkPool作为内部队列。
    • 没错。按照那个 JIRA 的 PR 链接到我不久前做的一个 PoC。它不完整,但证明了这个概念。
    • 我不知道你的 qos 问题的答案。询问 rabbitmq-users google 组中的 rabbitmq 人员。
    猜你喜欢
    • 2019-07-02
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    相关资源
    最近更新 更多