RabbitMQ 服務的SimpleMessageListenerContainer和DirectMessageListenerContainer

RabbitMQ 消費者代碼開發過程中會使用到 SimpleMessageListenerContainer 和 DirectMessageListenerContainer。
在版本2.0之前的版本中,只有一種MessageListenerContainer 即 SimpleMessageListenerContainer; 2.0之後有第二個容器—DirectMessageListenerContainer

一、SimpleMessageListenerContainer

默認情況下,偵聽器容器將啓動單個使用者,該使用者將從隊列接收消息。根據之前的文檔,我們知道有許多控制併發性的屬性。
最簡單的是concurrentConsumers,它只創建(固定的)將併發處理消息的使用者數量。
此外,還添加了一個新的屬性 maxConcurrentConsumers,容器將根據工作負載動態調整併發性。這與四個附加屬性一起工作:continutiveactivetrigger、startConsumerMinInterval、continutiveidletrigger、stopConsumerMinInterval。

1.1、在默認設置下,增加消費者的算法工作如下

如果尚未到達maxConcurrentConsumers,並且已有的使用者連續10個週期處於活動狀態,並且自上一個使用者啓動以來至少已經過了10秒,那麼將啓動一個新的使用者。如果使用者在txSize *中接收到至少一條消息,則認爲該使用者處於活動狀態。

1.2、在默認設置下,減少消費者的算法工作如下

如果有多個concurrentConsumers正在運行,並且某個consumer檢測到10個連續超時(空閒),並且上一個consumer至少在60秒之前停止,那麼該consumer將停止。超時取決於receiveTimeout和txSize屬性。如果使用者在txSize *中沒有接收到任何消息,則認爲它是空閒的。因此,在默認超時(1秒)和txSize爲4的情況下,在40秒的空閒時間(4個超時對應1個空閒檢測)之後將考慮停止使用者。

1.3、配置如下

@Bean
public SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(ConnectionFactory connectionFactory){
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    //初始化消費者數量
    factory.setConcurrentConsumers(this.concurrentConsumers);
    //最大消費者數量
    factory.setMaxConcurrentConsumers(this.maxConcurrentConsumers);
    //手動確認消息
    factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    factory.setErrorHandler(rabbitErrorHandler);
    return factory;
}

二、DirectMessageListenerContainer

使用 DirectMessageListenerContainer,您需要確保 ConnectionFactory 配置了一個任務執行器,該執行器在使用該 ConnectionFactory 的所有偵聽器容器中具有足夠的線程來支持所需的併發性。默認連接池大小僅爲5。
併發性基於配置的隊列和consumersPerQueue。每個隊列的每個使用者使用一個單獨的通道,併發性由rabbit客戶端庫控制;默認情況下,它使用5個線程池;您可以配置taskExecutor來提供所需的最大併發性。

2.1、配置如下

@Bean
public DirectRabbitListenerContainerFactory directRabbitListenerContainerFactory(ConnectionFactory connectionFactory){
    DirectRabbitListenerContainerFactory factory = new DirectRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    //每個隊列的消費者數量
    factory.setConsumersPerQueue(this.consumersPerQueue);
    //手動確認消息
    factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    factory.setErrorHandler(rabbitErrorHandler);
    return factory;
}

三、服務對比

SimpleMessageListenerContainer提供了以下特性,但DirectMessageListenerContainer不提供:

  1. txSize—使用SimpleMessageListenerContainer,您可以將其設置爲控制事務中傳遞的消息數量和/或減少ack的數量,但這可能會導致失敗後重復傳遞的數量增加。(與txSize和SimpleMessageListenerContainer一樣,DirectMessageListenerContainer也有mesagesPerAck,可以用來減少ack,但不能用於事務—每個消息都在單獨的事務中交付和打包)。
  2. maxconcurrentconsumer和consumer伸縮間隔/觸發器—DirectMessageListenerContainer中沒有自動伸縮;但是,它允許您以編程方式更改consumersPerQueue屬性,並相應地調整使用者。

然而,與SimpleMessageListenerContainer相比,DirectMessageListenerContainer有以下優點:

  1. 在運行時添加和刪除隊列更有效;使用SimpleMessageListenerContainer,整個使用者線程重新啓動(所有使用者取消並重新創建);對於DirectMessageListenerContainer,不受影響的使用者不會被取消。
  2. 避免了RabbitMQ客戶機線程和使用者線程之間的上下文切換。
  3. 線程是跨使用者共享的,而不是爲SimpleMessageListenerContainer中的每個使用者都有一個專用線程。但是,請參閱“線程和異步使用者”一節中有關連接工廠配置的重要說明。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章