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讨论使用 channel (全局)范围设置预取计数的开销。没有明确提及与根本不设置相比,使用消费者范围设置它是否有任何开销。如果我没记错的话,spring 总是将其设置为消费者范围。它真的没有任何开销吗?不过,没有不设置它的选项似乎很奇怪。
谢谢
最佳答案
由于当前的实现将交给内部队列,由于早期的rabbitmq客户端的工作方式,如果消费者跟不上,不设置qos将导致OOM情况。
事实上,在 Spring AMQP 的早期版本中,自动确认会发生这种情况,因此队列根据预取大小进行限制,以阻止代理在这种情况下发送消息。
在2.0中,我们是planning a new container implementation that avoids this queue因为兔子客户端不再有需要它的问题。那么我们可以考虑支持qos=0。
关于java - 如何使用 SimpleMessageListenerContainer 禁用 RabbitMQ 预取计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37764309/