Spring AMPQ多个消费者与更高的预取值

时间:2018-06-18 20:46:16

标签: spring-boot rabbitmq spring-amqp

即使在阅读了大量SO问题(12)和文章之后,还不清楚哪个是为消费者设置的更好选择。多个消费者或更高的预取值?

根据我的理解,当涉及到SimpleRabbitListenerContainerFactory,因为它最初设计为每个连接只有一个线程它被设计为解决仅限amqp-client的限制每个连接有一个线程,这是否意味着设置多个消费者不会产生很大的不同,因为只有一个线程实际上从兔子消费而不是将其交给多个消费者(线程)? 或者实际上有几个消费者在同一时间消费?

那么关于预取/消费者的兔子春季实施的最佳实践是什么?应该何时使用另一个?我应该切换到这个新DirectRabbitListenerContainerFactory吗?它是否更好'或者只是取决于用例?

在高预取时我看到的一些缺点是,如果应用程序消耗了更多可以保存在缓冲区中的消息,它可能会导致内存问题? (还没有实际测试过这个,tbh)

当谈到多个消费者时,我看到在操作系统级别打开更多文件描述符的缺点,我看到this文章说每个消费者实际上为每个ack ping兔子,这使得它变慢。 / p>

仅供参考,如果相关,我通常会将我的配置设置为:

@Bean
public ConnectionFactory connectionFactory() {
final CachingConnectionFactory connectionFactory = new CachingConnectionFactory(server);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setRequestedHeartBeat(requestedHeartBeat);
return connectionFactory;
}

@Bean
public AmqpAdmin amqpAdmin() {
    AmqpAdmin admin = new RabbitAdmin(connectionFactory());
    admin.declareQueue(getRabbitQueue());
    return admin;
}

@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
final SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setConcurrentConsumers(concurrency);
factory.setMaxConcurrentConsumers(maxConcurrency);
factory.setPrefetchCount(prefetch);
factory.setMissingQueuesFatal(false);
return factory;
}

@Bean
public Queue getRabbitQueue() {
final Map<String, Object> p = new HashMap<String, Object>();
p.put("x-max-priority", 10);
return new Queue(queueName, true, false, false, p);
}

1 个答案:

答案 0 :(得分:1)

没有; SMLC不是“为每个连接设计一个线程”,它旨在解决amqp-client每个连接只有一个线程的限制,以便线程通过内存队列切换到消费者线程;这已不再是这种情况。客户端是多线程的,每个消费者有一个专用线程。

拥有多个使用者(增加并发性)是完全有效的(即使使用较旧的客户端也是如此)。

预取实际上是为了减少网络抖动并提高整体吞吐量。是否需要增加并发性确实与预取正交。如果(a)您的侦听器处理每条消息的速度相对较慢,并且(b)严格的消息排序并不重要,则通常会增加并发性。

引入DirectListenerContainer以提供不同的线程模型,其中直接在amqp-client线程上调用侦听器。

Choosing a Container中描述了选择一个容器而不是另一个容器的原因。

  

SMLC提供以下功能,但不提供DMLC:

     
      
  • txSize - 使用SMLC,您可以将其设置为控制事务中传递的消息数量和/或减少确认数量,但可能会导致重复传递的次数失败后增加。 (DMLC确实有mesagesPerAck,它可用于减少ack,与txSize和SMLC相同,但它不能用于事务 - 每条消息都在单独的事务中传递和确认)。

  •   
  • maxConcurrentConsumers和消费者缩放间隔/触发器 - DMLC中没有自动缩放功能;但是,它允许您以编程方式更改consumersPerQueue属性,并相应地调整使用者。

  •   
     

然而,DMLC与SMLC相比具有以下优势:

     
      
  • 在运行时添加和删除队列效率更高;使用SMLC,重新启动整个消费者线程(所有消费者都被取消并重新创建);使用DMLC,未受影响的消费者不会被取消。

  •   
  • 避免在RabbitMQ客户端线程和使用者线程之间切换上下文。

  •   
  • 线程在消费者之间共享,而不是为SMLC中的每个消费者提供专用线程。但是,请参阅“线程和异步使用者”一节中有关连接工厂配置的重要说明。

  •