代码之家  ›  专栏  ›  技术社区  ›  Urosh T. Leo Zhao

spring-ampq多用户与更高的预取值

  •  2
  • Urosh T. Leo Zhao  · 技术社区  · 6 年前

    即使在读了很多这样的问题之后( 1 , 2 和文章,目前尚不清楚哪个是更好的选择为消费者设置。多个使用者还是更高的预取值?

    据我所知 SimpleRabbitListenerContainerFactory , 因为它最初的设计是每个连接只有一个线程 它的设计是为了解决一个限制,即AMQP客户端每个连接只有一个线程,这是否意味着设置多个消费者不会有太大的区别,因为只有一个线程实际上是从兔子消费的,而不是把它交给多个消费者(线程)? 还是实际上有几个消费者同时消费?

    那么,关于兔子的预取/消费者的春天实施,最好的做法是什么?什么时候用一个代替另一个?我应该换成这个新的 DirectRabbitListenerContainerFactory ?是“更好”还是仅仅取决于用例?

    在高预取时,我看到的一些缺点是,如果一个应用程序消耗了更多的消息,那么它可能会导致内存问题。(尚未实际测试,待定)

    当涉及到多个消费者时,我看到了在操作系统级别打开更多文件描述符的缺点,我看到了 this 文章说,每个消费者实际上为每个ACK兔子,这使它慢。

    FY,如果它是相关的,我通常会这样配置:

    @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 回复  |  直到 6 年前
        1
  •  1
  •   Gary Russell    6 年前

    不,SMLC不是“为每个线程设计一个线程”,它的设计是为了解决一个限制,即AMQP客户端每连接只有一个线程,以便线程通过内存队列切换到用户线程;不再是这样。客户机是多线程的,每个客户机有一个专用线程。

    拥有多个使用者(增加并发性)是完全有效的(甚至在旧客户机上也是如此)。

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

    这个 DirectListenerContainer 引入了一种不同的线程模型,其中直接在AMQP客户端线程上调用侦听器。

    选择一个容器而不是另一个容器的原因在 Choosing a Container .

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

    • txSize -使用SMLC,您可以将其设置为控制事务中传递的消息数量和/或减少ACK的数量,但这可能会导致失败后重复传递的数量增加。(DMLC确实有MeaGeSpPACK,它可以用来减少ACK,与TxSead和SMLC相同,但是它不能用于事务——每个消息在单独的事务中被传递和ACKD)。

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

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

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

    • 避免了rabbitmq客户机线程和使用者线程之间的上下文切换。

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