监听器并发
SimpleMessageListenerContainer
默认情况下,监听器容器启动单个消费者,从队列接收消息。
查看上一节中的表格时,你会看到许多控制并发的属性和属性项。最简单的是 concurrentConsumers,它会创建该(固定)数量的消费者来并发处理消息。
在 1.3.0 版本之前,这是唯一可用的设置,并且必须停止容器再重新启动才能更改该设置。
从 1.3.0 版本开始,你现在可以动态调整 concurrentConsumers 属性。如果在容器运行期间更改它,容器会根据需要添加或移除消费者,以适应新的设置。
此外,还新增了一个名为 maxConcurrentConsumers 的属性,容器会根据工作负载动态调整并发数。它与另外四个属性协同工作:consecutiveActiveTrigger、startConsumerMinInterval、consecutiveIdleTrigger 和 stopConsumerMinInterval。在默认设置下,增加消费者的算法如下:
如果尚未达到 maxConcurrentConsumers,并且某个现有消费者连续十个周期都处于活跃状态,而且自上一个消费者启动以来至少已经过去 10 秒,则启动一个新消费者。如果一个消费者在 batchSize * receiveTimeout 毫秒内至少收到一条消息,则认为它处于活跃状态。
在默认设置下,减少消费者的算法如下:
如果运行中的消费者多于 concurrentConsumers,并且某个消费者检测到连续十次超时(空闲),而且距上一个消费者停止至少已过去 60 秒,则停止一个消费者。超时时间取决于 receiveTimeout 和 batchSize 属性。如果一个消费者在 batchSize * receiveTimeout 毫秒内没有收到消息,则认为它处于空闲状态。因此,在默认超时(一秒)和 batchSize 为四的情况下,经过 40 秒空闲时间后才会考虑停止消费者(四次超时对应一次空闲检测)。
实际上,只有当整个容器空闲一段时间后,才能停止消费者。这是因为 broker 会把它的工作分配给所有活跃的消费者。
无论配置了多少个队列,每个消费者都使用单个 channel。
从 2.0 版本开始,可以通过 concurrency 属性设置 concurrentConsumers 和 maxConcurrentConsumers 属性——例如 2-4。
使用 DirectMessageListenerContainer
对于这个容器,并发数基于已配置的队列和 consumersPerQueue。每个队列的每个消费者都使用单独的 channel,并发数由 rabbit 客户端库控制。在撰写本文时,它默认使用一个 DEFAULT_NUM_THREADS = Runtime.getRuntime().availableProcessors() * 2 线程池。
你可以配置一个 taskExecutor 来提供所需的最大并发数。