接続とリソースの管理

前のセクションで説明した AMQP モデルは一般的であり、すべての実装に適用できますが、リソースの管理に入ると、詳細はブローカーの実装に固有のものになります。このセクションでは、"spring-rabbit" モジュール内にのみ存在するコードに焦点を当てます。こでは、RabbitMQ がサポートされている唯一の実装であるためです。

RabbitMQ ブローカーへの接続を管理する中心的なコンポーネントは、ConnectionFactory インターフェースです。ConnectionFactory 実装の責任は、com.rabbitmq.client.Connection のラッパーである org.springframework.amqp.rabbit.connection.Connection のインスタンスを提供することです。

接続ファクトリの選択

3 つの接続ファクトリから選択できます

  • PooledChannelConnectionFactory

  • ThreadChannelConnectionFactory

  • CachingConnectionFactory

最初の 2 つはバージョン 2.3 で追加されました。

ほとんどの使用例では、CachingConnectionFactory を使用する必要があります。ThreadChannelConnectionFactory は、範囲指定された操作を使用せずにメッセージの厳密な順序付けを保証したい場合に使用できます。PooledChannelConnectionFactory は、単一の接続とチャネルのプールを使用するという点で CachingConnectionFactory に似ています。実装はより簡単ですが、関連付けられたパブリッシャーの確認はサポートされていません。

簡単な発行元の確認は、3 つのファクトリすべてでサポートされています。

別の接続を使用するように RabbitTemplate を構成する場合、バージョン 2.3.2 以降では、公開接続ファクトリを別の型に構成できるようになりました。デフォルトでは、パブリッシングファクトリは同じ型であり、メインファクトリに設定されたすべてのプロパティもパブリッシングファクトリに伝達されます。

バージョン 3.1 以降、AbstractConnectionFactory には、接続モジュールのバックオフポリシーをサポートする connectionCreatingBackOff プロパティが含まれています。現在、createChannel() の動作では、channelMax 制限に達したときに発生する例外を処理するサポートがあり、試行と間隔に基づいたバックオフ戦略が実装されています。

PooledChannelConnectionFactory

このファクトリは、Apache Pool2 に基づいて、単一の接続と 2 つのチャネルプールを管理します。1 つのプールはトランザクションチャネル用で、もう 1 つは非トランザクションチャネル用です。プールは、デフォルト構成の GenericObjectPool です。プールを構成するためのコールバックが提供されています。詳細については、Apache のドキュメントを参照してください。

このファクトリを使用するには、Apache commons-pool2 jar がクラスパス上に存在している必要があります。

@Bean
PooledChannelConnectionFactory pcf() throws Exception {
    ConnectionFactory rabbitConnectionFactory = new ConnectionFactory();
    rabbitConnectionFactory.setHost("localhost");
    PooledChannelConnectionFactory pcf = new PooledChannelConnectionFactory(rabbitConnectionFactory);
    pcf.setPoolConfigurer((pool, tx) -> {
        if (tx) {
            // configure the transactional pool
        }
        else {
            // configure the non-transactional pool
        }
    });
    return pcf;
}

ThreadChannelConnectionFactory

このファクトリは、1 つの接続と 2 つの ThreadLocal を管理します。1 つはトランザクションチャネル用で、もう 1 つは非トランザクションチャネル用です。このファクトリは、同じスレッドに対するすべての操作が同じチャネルを使用することを保証します (開いている限り)。これにより、範囲指定された操作を必要とせずに厳密なメッセージの順序付けが容易になります。アプリケーションが有効期間の短いスレッドを多数使用する場合、メモリリークを回避するには、ファクトリの closeThreadChannel() を呼び出してチャネルリソースを解放する必要があります。バージョン 2.3.7 以降、スレッドはそのチャネルを別のスレッドに転送できます。詳細については、マルチスレッド環境での厳密なメッセージの順序付けを参照してください。

CachingConnectionFactory

提供される 3 番目の実装は CachingConnectionFactory です。これは、デフォルトで、アプリケーションで共有できる単一の接続プロキシを確立します。AMQP とのメッセージングの「作業単位」は実際には「チャネル」であるため、接続の共有が可能です (ある意味では、これは JMS における接続とセッションの関連に似ています)。接続インスタンスは createChannel メソッドを提供します。CachingConnectionFactory 実装は、これらのチャネルのキャッシングをサポートし、チャネルがトランザクションかどうかに基づいて、チャネルごとに個別のキャッシュを維持します。CachingConnectionFactory のインスタンスを作成する場合、コンストラクターを介して「ホスト名」を指定できます。また、'username' および 'password' プロパティも指定する必要があります。チャネルキャッシュのサイズ (デフォルトは 25) を構成するには、setChannelCacheSize() メソッドを呼び出します。

バージョン 1.3 以降では、CachingConnectionFactory を構成して、チャネルだけでなく接続もキャッシュすることができます。この場合、createConnection() を呼び出すたびに、新しい接続が作成されます (または、アイドル状態の接続がキャッシュから取得されます)。接続を閉じると、接続がキャッシュに戻されます (キャッシュサイズに達していない場合)。このような接続で作成されたチャネルもキャッシュされます。別の接続の使用は、HA クラスターから消費する場合や、ロードバランサーと組み合わせて異なるクラスターメンバーに接続する場合など、一部の環境で役立つ場合があります。接続をキャッシュするには、cacheMode を CacheMode.CONNECTION に設定します。

これは、接続数を制限しません。むしろ、許可されるアイドル状態のオープン接続の数を指定します。

バージョン 1.5.5 以降、connectionLimit と呼ばれる新しいプロパティが提供されます。このプロパティを設定すると、許可される接続の総数が制限されます。設定すると、制限に達した場合、接続がアイドル状態になるのを待機するために channelCheckoutTimeLimit が使用されます。時間を超えると、AmqpTimeoutException がスローされます。

キャッシュモードが CONNECTION の場合、キューなどの自動宣言 ( 交換、キュー、バインディングの自動宣言を参照) はサポートされません。

また、このドキュメントの記載時点では、amqp-client ライブラリはデフォルトで接続ごとに固定スレッドプールを作成します (デフォルトサイズ: Runtime.getRuntime().availableProcessors() * 2 スレッド)。多数の接続を使用する場合は、CachingConnectionFactory でカスタム executor を設定することを検討する必要があります。次に、同じエグゼキュータをすべての接続で使用でき、そのスレッドを共有できます。エグゼキュータのスレッドプールは、無制限にするか、予想される用途に合わせて適切に設定する必要があります (通常、接続ごとに少なくとも 1 つのスレッド)。各接続で複数のチャネルが作成される場合、プールサイズは同時実行性に影響するため、可変 (または単純にキャッシュされた) スレッドプールエグゼキューターが最適です。

キャッシュサイズは (デフォルトでは) 制限ではなく、単にキャッシュできるチャネルの数であることを理解することが重要です。たとえば 10 のキャッシュサイズでは、実際には任意の数のチャネルを使用できます。10 を超えるチャネルが使用されていて、それらがすべてキャッシュに返される場合、10 がキャッシュに入ります。残りは物理的に閉鎖されています。

バージョン 1.6 から、デフォルトのチャネルキャッシュサイズが 1 から 25 に増加しました。大量のマルチスレッド環境では、キャッシュが小さいということは、チャネルが高速で作成され、閉じられることを意味します。デフォルトのキャッシュサイズを大きくすると、このオーバーヘッドを回避できます。RabbitMQ 管理 UI を使用して使用中のチャネルを監視し、多くのチャネルが作成されて閉じられている場合は、キャッシュサイズをさらに増やすことを検討する必要があります。キャッシュは (アプリケーションの同時実行要件に合わせて) オンデマンドでのみ拡張されるため、この変更は既存の少量のアプリケーションには影響しません。

バージョン 1.4.2 以降、CachingConnectionFactory には channelCheckoutTimeout というプロパティがあります。このプロパティが 0 より大きい場合、channelCacheSize は、接続で作成できるチャネル数の制限になります。制限に達すると、チャネルが使用可能になるか、このタイムアウトに達するまでスレッドの呼び出しがブロックされます。この場合、AmqpTimeoutException がスローされます。

フレームワーク内で使用されるチャネル ( RabbitTemplate など) は、確実にキャッシュに返されます。フレームワークの外部でチャネルを作成する場合 (たとえば、接続に直接アクセスして createChannel() を呼び出すことによって)、チャネルが不足しないように、おそらく finally ブロックで (閉じることによって) 確実に返す必要があります。

次の例は、新しい connection を作成する方法を示しています。

CachingConnectionFactory connectionFactory = new CachingConnectionFactory("somehost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");

Connection connection = connectionFactory.createConnection();

XML を使用する場合、構成は次の例のようになります。

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
    <constructor-arg value="somehost"/>
    <property name="username" value="guest"/>
    <property name="password" value="guest"/>
</bean>
フレームワークの単体テストコードでのみ使用できる SingleConnectionFactory 実装もあります。チャネルをキャッシュしないため、CachingConnectionFactory よりも単純ですが、パフォーマンスと回復力が不足しているため、単純なテスト以外での実用的な使用は意図されていません。なんらかの理由で独自の ConnectionFactory を実装する必要がある場合、AbstractConnectionFactory 基底クラスが適切な出発点となる場合があります。

ConnectionFactory は、次のように rabbit 名前空間を使用して迅速かつ便利に作成できます。

<rabbit:connection-factory id="connectionFactory"/>

ほとんどの場合、フレームワークが最適なデフォルトを選択できるため、このアプローチが推奨されます。作成されたインスタンスは CachingConnectionFactory です。チャネルのデフォルトのキャッシュサイズは 25 であることに注意してください。より多くのチャネルをキャッシュする場合は、'channelCacheSize' プロパティを設定してより大きな値を設定します。XML では、次のようになります。

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
    <constructor-arg value="somehost"/>
    <property name="username" value="guest"/>
    <property name="password" value="guest"/>
    <property name="channelCacheSize" value="50"/>
</bean>

また、名前空間を使用して、次のように 'channel-cache-size' 属性 を追加できます。

<rabbit:connection-factory
    id="connectionFactory" channel-cache-size="50"/>

デフォルトのキャッシュモードは CHANNEL ですが、代わりに接続をキャッシュするように構成できます。次の例では、connection-cache-size を使用します。

<rabbit:connection-factory
    id="connectionFactory" cache-mode="CONNECTION" connection-cache-size="25"/>

次のように、名前空間を使用してホストとポートの属性を指定できます。

<rabbit:connection-factory
    id="connectionFactory" host="somehost" port="5672"/>

あるいは、クラスター環境で実行している場合は、次のように addresses 属性を使用できます。

<rabbit:connection-factory
    id="connectionFactory" addresses="host1:5672,host2:5672" address-shuffle-mode="RANDOM"/>

address-shuffle-mode については、クラスターへの接続を参照してください。

次の例では、スレッド名の前に rabbitmq- を付けるカスタムスレッドファクトリを使用しています。

<rabbit:connection-factory id="multiHost" virtual-host="/bar" addresses="host1:1234,host2,host3:4567"
    thread-factory="tf"
    channel-cache-size="10" username="user" password="password" />

<bean id="tf" class="org.springframework.scheduling.concurrent.CustomizableThreadFactory">
    <constructor-arg value="rabbitmq-" />
</bean>

AddressResolver

バージョン 2.1.15 から、AddressResolver を使用して接続アドレスを解決できるようになりました。これにより、addresses および host/port プロパティの設定が上書きされます。

命名接続

バージョン 1.7 以降、AbstractionConnectionFactory への注入用に ConnectionNameStrategy が提供されています。生成された名前は、ターゲット RabbitMQ 接続のアプリケーション固有の識別に使用されます。RabbitMQ サーバーがサポートしている場合、接続名は管理 UI に表示されます。この値は一意である必要はなく、HTTP API リクエストなどで接続識別子として使用することはできません。この値は、人間が判読できると想定されており、connection_name キーの ClientProperties の一部です。次のように、単純な Lambda を使用できます。

connectionFactory.setConnectionNameStrategy(connectionFactory -> "MY_CONNECTION");

ConnectionFactory 引数を使用して、ロジックによってターゲット接続名を区別できます。デフォルトでは、AbstractConnectionFactory の beanName、オブジェクトを表す 16 進文字列、および内部カウンターを使用して connection_name が生成されます。<rabbit:connection-factory> 名前空間コンポーネントには、connection-name-strategy 属性も提供されます。

SimplePropertyValueConnectionNameStrategy の実装は、接続名をアプリケーションプロパティに設定します。次の例に示すように、これを @Bean として宣言し、接続ファクトリに挿入できます。

@Bean
public SimplePropertyValueConnectionNameStrategy cns() {
    return new SimplePropertyValueConnectionNameStrategy("spring.application.name");
}

@Bean
public ConnectionFactory rabbitConnectionFactory(ConnectionNameStrategy cns) {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
    ...
    connectionFactory.setConnectionNameStrategy(cns);
    return connectionFactory;
}

プロパティは、アプリケーションコンテキストの Environment に存在する必要があります。

Spring Boot とその自動構成された接続ファクトリを使用する場合、ConnectionNameStrategy@Bean を宣言するだけで済みます。Boot は Bean を自動検出し、ファクトリに接続します。

ブロックされた接続とリソースの制約

メモリアラーム (英語) に対応するブローカーからの対話に対して、接続がブロックされている可能性があります。バージョン 2.0 から、org.springframework.amqp.rabbit.connection.Connection に com.rabbitmq.client.BlockedListener インスタンスを提供して、接続のブロックおよびブロック解除のイベントを通知できます。さらに、AbstractConnectionFactory は、内部の BlockedListener 実装を通じて、それぞれ ConnectionBlockedEvent と ConnectionUnblockedEvent を発行します。これらを使用すると、アプリケーションロジックを提供して、ブローカーの問題に適切に対応し、(たとえば) 修正アクションを実行できます。

アプリケーションが単一の CachingConnectionFactory で構成されている場合、デフォルトでは Spring Boot 自動構成で構成されているため、ブローカーによって接続がブロックされると、アプリケーションは動作を停止します。また、ブローカーによってブロックされると、そのクライアントのいずれかが機能しなくなります。同じアプリケーションにプロデューサーとコンシューマーがある場合、プロデューサーが接続をブロックし (ブローカーにリソースがなくなったため)、コンシューマーが解放できない (接続がブロックされているため) 場合、デッドロックが発生する可能性があります。この問題を軽減するために、同じオプション (プロデューサー用とコンシューマー用) を持つ別の CachingConnectionFactory インスタンスをもう 1 つ用意することをお勧めします。コンシューマースレッドで実行されるトランザクションプロデューサーでは、コンシューマートランザクションに関連付けられた Channel を再利用する必要があるため、別個の CachingConnectionFactory は使用できません。

バージョン 2.0.2 以降、RabbitTemplate には、トランザクションが使用されていない限り、2 番目の接続ファクトリを自動的に使用する構成オプションがあります。詳細については、別の接続を使用するを参照してください。パブリッシャー接続の ConnectionNameStrategy は、メソッドの呼び出し結果に .publisher が追加されたプライマリ戦略と同じです。

バージョン 1.7.7 から、SimpleConnection.createChannel() が Channel を作成できない場合にスローされる AmqpResourceNotAvailableException が提供されます (たとえば、channelMax 制限に達し、キャッシュに使用可能なチャネルがないため)。RetryPolicy でこの例外を使用して、何らかのバックオフ後に操作を回復できます。

基礎となるクライアント接続ファクトリの構成

CachingConnectionFactory は、Rabbit クライアント ConnectionFactory のインスタンスを使用します。CachingConnectionFactory で同等のプロパティを設定する場合、多くの構成プロパティ (hostportuserNamepasswordrequestedHeartBeatconnectionTimeout など) が渡されます。他のプロパティ (clientProperties など) を設定するには、Rabbit ファクトリのインスタンスを定義し、CachingConnectionFactory の適切なコンストラクターを使用してそのインスタンスへの参照を提供します。ネームスペースを使用する場合 ( 前述のとおり )、connection-factory 属性で構成されたファクトリへの参照を提供する必要があります。便宜上、次のセクションで説明するように、Spring アプリケーションコンテキストでの接続ファクトリの構成を支援するファクトリ Bean が提供されています。

<rabbit:connection-factory
      id="connectionFactory" connection-factory="rabbitConnectionFactory"/>
4.0.x クライアントは、デフォルトで自動回復を有効にします。この機能と互換性がありますが、Spring AMQP には独自の回復メカニズムがあり、通常、クライアント回復機能は必要ありません。ブローカーが使用可能であるが接続がまだ回復していない場合に AutoRecoverConnectionNotCurrentlyOpenException インスタンスを取得しないように、amqp-client 自動回復を無効にすることをお勧めします。たとえば、RetryTemplate が RabbitTemplate で構成されている場合、クラスター内の別のブローカーにフェイルオーバーする場合でも、この例外に気付く場合があります。自動回復接続はタイマーで回復するため、Spring AMQP の回復メカニズムを使用すると、接続をより迅速に回復できます。バージョン 1.7.1 以降、Spring AMQP は、独自の RabbitMQ 接続ファクトリを明示的に作成して CachingConnectionFactory に提供しない限り、amqp-client 自動回復を無効にします。RabbitConnectionFactoryBean によって作成された RabbitMQ ConnectionFactory インスタンスでも、デフォルトでオプションが無効になっています。

RabbitConnectionFactoryBean と SSL の構成

バージョン 1.4 以降では、依存性注入を使用して、基になるクライアント接続ファクトリで SSL プロパティを簡単に構成できる便利な RabbitConnectionFactoryBean が提供されています。その他の setter は、基になるファクトリにデリゲートします。以前は、SSL オプションをプログラムで構成する必要がありました。次の例は、RabbitConnectionFactoryBean を構成する方法を示しています。

Java
@Bean
RabbitConnectionFactoryBean rabbitConnectionFactory() {
    RabbitConnectionFactoryBean factoryBean = new RabbitConnectionFactoryBean();
    factoryBean.setUseSSL(true);
    factoryBean.setSslPropertiesLocation(new ClassPathResource("secrets/rabbitSSL.properties"));
    return factoryBean;
}

@Bean
CachingConnectionFactory connectionFactory(ConnectionFactory rabbitConnectionFactory) {
    CachingConnectionFactory ccf = new CachingConnectionFactory(rabbitConnectionFactory);
    ccf.setHost("...");
    // ...
    return ccf;
}
Boot application.properties
spring.rabbitmq.ssl.enabled:true
spring.rabbitmq.ssl.keyStore=...
spring.rabbitmq.ssl.keyStoreType=jks
spring.rabbitmq.ssl.keyStorePassword=...
spring.rabbitmq.ssl.trustStore=...
spring.rabbitmq.ssl.trustStoreType=jks
spring.rabbitmq.ssl.trustStorePassword=...
spring.rabbitmq.host=...
...
XML
<rabbit:connection-factory id="rabbitConnectionFactory"
    connection-factory="clientConnectionFactory"
    host="${host}"
    port="${port}"
    virtual-host="${vhost}"
    username="${username}" password="${password}" />

<bean id="clientConnectionFactory"
        class="org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean">
    <property name="useSSL" value="true" />
    <property name="sslPropertiesLocation" value="classpath:secrets/rabbitSSL.properties"/>
</bean>

SSL の構成については、RabbitMQ ドキュメント (英語) を参照してください。keyStore および trustStore 構成を省略して、証明書の検証なしで SSL 経由で接続します。次の例は、キーとトラストストアの構成を提供する方法を示しています。

sslPropertiesLocation プロパティは、次のキーを含むプロパティファイルを指す Spring Resource です。

keyStore=file:/secret/keycert.p12
trustStore=file:/secret/trustStore
keyStore.passPhrase=secret
trustStore.passPhrase=secret

keyStore および truststore は、ストアを指す Spring Resources です。通常、このプロパティファイルはオペレーティングシステムによって保護され、アプリケーションは読み取りアクセス権を持っています。

Spring AMQP バージョン 1.5 以降では、提供時の Bean でこれらのプロパティを直接設定できます。離散プロパティと sslPropertiesLocation の両方が指定されている場合、後者のプロパティが離散値をオーバーライドします。

バージョン 2.0 以降、サーバー証明書はより安全であるため、デフォルトで検証されます。何らかの理由でこの検証をスキップしたい場合は、ファクトリ Bean の skipServerCertificateValidation プロパティを true に設定してください。バージョン 2.1 から、RabbitConnectionFactoryBean はデフォルトで enableHostnameVerification() を呼び出すようになりました。以前の動作に戻すには、enableHostnameVerification プロパティを false に設定します。
バージョン 2.2.5 以降、ファクトリ Bean は常にデフォルトで TLS v1.2 を使用します。以前は、場合によっては v1.1 を使用し、他の場合には v1.2 を使用していました (他のプロパティによって異なります)。何らかの理由で v1.1 を使用する必要がある場合は、sslAlgorithm プロパティを設定します: setSslAlgorithm("TLSv1.1")

クラスターへの接続

クラスターに接続するには、CachingConnectionFactory で addresses プロパティを構成します。

@Bean
public CachingConnectionFactory ccf() {
    CachingConnectionFactory ccf = new CachingConnectionFactory();
    ccf.setAddresses("host1:5672,host2:5672,host3:5672");
    return ccf;
}

バージョン 3.0 から、新しい接続が確立されるたびに、基になる接続ファクトリがランダムなアドレスを選択してホストへの接続を試みます。最初から最後まで接続を試行する以前の動作に戻すには、addressShuffleMode プロパティを AddressShuffleMode.NONE に設定します。

バージョン 2.3 から、INORDER シャッフルモードが追加されました。これは、接続が作成された後に最初のアドレスが最後に移動されることを意味します。すべてのノードのすべてのシャードから消費したい場合は、CacheMode.CONNECTION と適切な同時実行性を備えた RabbitMQ シャーディングプラグイン [GitHub] (英語) でこのモードを使用することをお勧めします。

@Bean
public CachingConnectionFactory ccf() {
    CachingConnectionFactory ccf = new CachingConnectionFactory();
    ccf.setAddresses("host1:5672,host2:5672,host3:5672");
    ccf.setAddressShuffleMode(AddressShuffleMode.INORDER);
    return ccf;
}

ルーティング接続ファクトリ

バージョン 1.3 から、AbstractRoutingConnectionFactory が導入されました。このファクトリは、複数の ConnectionFactories のマッピングを構成し、実行時に一部の lookupKey によってターゲット ConnectionFactory を決定するメカニズムを提供します。通常、実装はスレッドにバインドされたコンテキストをチェックします。便宜上、Spring AMQP は SimpleRoutingConnectionFactory を提供します。これは、現在のスレッドにバインドされた lookupKey を SimpleResourceHolder から取得します。次の例は、XML と Java の両方で SimpleRoutingConnectionFactory を構成する方法を示しています。

<bean id="connectionFactory"
      class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
    <property name="targetConnectionFactories">
        <map>
            <entry key="#{connectionFactory1.virtualHost}" ref="connectionFactory1"/>
            <entry key="#{connectionFactory2.virtualHost}" ref="connectionFactory2"/>
        </map>
    </property>
</bean>

<rabbit:template id="template" connection-factory="connectionFactory" />
public class MyService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void service(String vHost, String payload) {
        SimpleResourceHolder.bind(rabbitTemplate.getConnectionFactory(), vHost);
        rabbitTemplate.convertAndSend(payload);
        SimpleResourceHolder.unbind(rabbitTemplate.getConnectionFactory());
    }

}

使用後はリソースのバインドを解除することが重要です。詳細については、AbstractRoutingConnectionFactoryJavaDoc (Javadoc) を参照してください。

バージョン 1.4 以降、RabbitTemplate は SpEL sendConnectionFactorySelectorExpression および receiveConnectionFactorySelectorExpression プロパティをサポートします。これらは、各 AMQP プロトコルインタラクション操作 (sendsendAndReceivereceive または receiveAndReply) で評価され、提供された AbstractRoutingConnectionFactory の lookupKey 値に解決されます。式で @vHostResolver.getVHost(#root) などの Bean 参照を使用できます。send 操作の場合、送信されるメッセージはルート評価オブジェクトです。receive 操作の場合、queueName はルート評価オブジェクトです。

ルーティングアルゴリズムは次のとおりです。セレクター式が null であるか、null に評価されるか、指定された ConnectionFactory が AbstractRoutingConnectionFactory のインスタンスではない場合、すべてが以前と同様に機能し、提供された ConnectionFactory 実装に依存します。評価結果が null ではなく、その lookupKey のターゲット ConnectionFactory がなく、AbstractRoutingConnectionFactory が lenientFallback = true で構成されている場合も同様です。AbstractRoutingConnectionFactory の場合、determineCurrentLookupKey() に基づく routing 実装にフォールバックします。ただし、lenientFallback = false の場合は、IllegalStateException がスローされます。

名前空間サポートは、<rabbit:template> コンポーネントの send-connection-factory-selector-expression および receive-connection-factory-selector-expression 属性も提供します。

また、バージョン 1.4 以降では、リスナーコンテナーでルーティング接続ファクトリを構成できます。その場合、キュー名のリストが検索キーとして使用されます。例: コンテナーを setQueueNames("thing1", "thing2") で構成する場合、検索キーは [thing1,thing]" です (キーにスペースがないことに注意してください)。

バージョン 1.6.9 以降では、リスナーコンテナーで setLookupKeyQualifier を使用して、ルックアップキーに修飾子を追加できます。これにより、たとえば、同じ名前で別の仮想ホスト (それぞれに接続ファクトリがある) にあるキューをリッスンできます。

例: ルックアップキー修飾子 thing1 とキュー thing2 をリッスンするコンテナーを使用すると、ターゲット接続ファクトリを登録できるルックアップキーは thing1[thing2] になる可能性があります。

ターゲット (および提供されている場合はデフォルト) 接続ファクトリは、パブリッシャーの確認と戻りに対して同じ設定を持っている必要があります。パブリッシャーの確認と return を参照してください。

バージョン 2.4.4 以降では、この検証を無効にすることができます。確認と return の間の値が等しくない必要がある場合は、AbstractRoutingConnectionFactory#setConsistentConfirmsReturns を使用して検証を無効にすることができます。AbstractRoutingConnectionFactory に追加された最初の接続ファクトリによって、confirms および returns の一般的な値が決定されることに注意してください。

確認したいメッセージが確認 /return され、そうでないメッセージがある場合に便利です。例:

@Bean
public RabbitTemplate rabbitTemplate() {
    final com.rabbitmq.client.ConnectionFactory cf = new com.rabbitmq.client.ConnectionFactory();
    cf.setHost("localhost");
    cf.setPort(5672);

    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(cf);
    cachingConnectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);

    PooledChannelConnectionFactory pooledChannelConnectionFactory = new PooledChannelConnectionFactory(cf);

    final Map<Object, ConnectionFactory> connectionFactoryMap = new HashMap<>(2);
    connectionFactoryMap.put("true", cachingConnectionFactory);
    connectionFactoryMap.put("false", pooledChannelConnectionFactory);

    final AbstractRoutingConnectionFactory routingConnectionFactory = new SimpleRoutingConnectionFactory();
    routingConnectionFactory.setConsistentConfirmsReturns(false);
    routingConnectionFactory.setDefaultTargetConnectionFactory(pooledChannelConnectionFactory);
    routingConnectionFactory.setTargetConnectionFactories(connectionFactoryMap);

    final RabbitTemplate rabbitTemplate = new RabbitTemplate(routingConnectionFactory);

    final Expression sendExpression = new SpelExpressionParser().parseExpression(
            "messageProperties.headers['x-use-publisher-confirms'] ?: false");
    rabbitTemplate.setSendConnectionFactorySelectorExpression(sendExpression);
}

こうすることで、ヘッダー x-use-publisher-confirms: true を持つメッセージがキャッシュ接続を通じて送信され、メッセージを確実に配信できます。確実なメッセージ配信の詳細については、"パブリッシャーの確認と return" を参照してください。

キューアフィニティと LocalizedQueueConnectionFactory

クラスター内で HA キューを使用する場合、最高のパフォーマンスを得るために、リードキューが存在する物理ブローカーに接続することができます。CachingConnectionFactory は複数のブローカーアドレスを使用して構成できます。これはフェイルオーバーのためであり、クライアントは構成された AddressShuffleMode 順序に従って接続を試みます。LocalizedQueueConnectionFactory は、管理プラグインによって提供される REST API を使用して、どのノードがキューのリードであるかを決定します。次に、そのノードだけに接続する CachingConnectionFactory を作成 (またはキャッシュから取得) します。接続が失敗した場合、新しいリードノードが決定され、コンシューマーはそこに接続します。LocalizedQueueConnectionFactory は、キューの物理的な場所を特定できない場合に備えて、デフォルトの接続ファクトリを使用して構成されます。この場合、LocalizedQueueConnectionFactory は通常どおりクラスターに接続します。

LocalizedQueueConnectionFactory は RoutingConnectionFactory であり、SimpleMessageListenerContainer は、上記のルーティング接続ファクトリで説明したように、キュー名をルックアップキーとして使用します。

この理由 (ルックアップにキュー名を使用) から、コンテナーが単一のキューをリッスンするように構成されている場合にのみ、LocalizedQueueConnectionFactory を使用できます。
各ノードで RabbitMQ 管理プラグインを有効にする必要があります。
この接続ファクトリは、SimpleMessageListenerContainer で使用される接続など、存続期間の長い接続を対象としています。接続を確立する前に REST API を呼び出すオーバーヘッドがあるため、RabbitTemplate などの短い接続での使用は想定されていません。また、パブリッシュ操作の場合、キューは不明であり、メッセージはすべてのクラスターメンバーにパブリッシュされるため、ノードを検索するロジックにはほとんど価値がありません。

次の構成例は、ファクトリを構成する方法を示しています。

@Autowired
private ConfigurationProperties props;

@Bean
public CachingConnectionFactory defaultConnectionFactory() {
    CachingConnectionFactory cf = new CachingConnectionFactory();
    cf.setAddresses(this.props.getAddresses());
    cf.setUsername(this.props.getUsername());
    cf.setPassword(this.props.getPassword());
    cf.setVirtualHost(this.props.getVirtualHost());
    return cf;
}

@Bean
public LocalizedQueueConnectionFactory queueAffinityCF(
        @Qualifier("defaultConnectionFactory") ConnectionFactory defaultCF) {
    return new LocalizedQueueConnectionFactory(defaultCF,
            StringUtils.commaDelimitedListToStringArray(this.props.getAddresses()),
            StringUtils.commaDelimitedListToStringArray(this.props.getAdminUris()),
            StringUtils.commaDelimitedListToStringArray(this.props.getNodes()),
            this.props.getVirtualHost(), this.props.getUsername(), this.props.getPassword(),
            false, null);
}

最初の 3 つのパラメーターは addressesadminUrisnodes の配列であることに注意してください。これらは、コンテナーがキューに接続しようとすると、管理 API を使用してどのノードがキューのリードであるかを判断し、そのノードと同じ配列位置のアドレスに接続するという点で位置的です。

バージョン 3.0 以降、RabbitMQ http-client は Rest API へのアクセスに使用されなくなりました。代わりに、デフォルトでは、spring-webflux がクラスパス上にある場合、Spring Webflux の WebClient が使用されます。それ以外の場合は、RestTemplate が使用されます。

WebFlux をクラスパスに追加するには:

<dependency>
  <groupId>org.springframework.amqp</groupId>
  <artifactId>spring-rabbit</artifactId>
</dependency>
compile 'org.springframework.amqp:spring-rabbit'

LocalizedQueueConnectionFactory.NodeLocator を実装し、その createClient, ``restCall およびオプションで close メソッドをオーバーライドすることにより、他の REST テクノロジを使用することもできます。

lqcf.setNodeLocator(new NodeLocator<MyClient>() {

    @Override
    public MyClient createClient(String userName, String password) {
        ...
    }

    @Override
    public HashMap<String, Object> restCall(MyClient client, URI uri) {
        ...
    });

});

フレームワークは WebFluxNodeLocator と RestTemplateNodeLocator を提供し、上記で説明したデフォルトを使用します。

パブリッシャーの確認と return

CachingConnectionFactory プロパティ publisherConfirmType を ConfirmType.CORRELATED に設定し、publisherReturns プロパティを "true" に設定することにより、確認済み (相関あり) および返されたメッセージがサポートされます。

これらのオプションが設定されている場合、ファクトリによって作成された Channel インスタンスは、コールバックを容易にするために使用される PublisherCallbackChannel にラップされます。このようなチャネルを取得すると、クライアントは PublisherCallbackChannel.Listener を Channel に登録できます。PublisherCallbackChannel 実装には、confirm または return を適切なリスナーにルーティングするためのロジックが含まれています。これらの機能については、以降のセクションで詳しく説明します。

範囲指定された操作相関するパブリッシャーの確認と return および simplePublisherConfirms も参照してください。

その他の背景情報については、RabbitMQ チームによるパブリッシャー確認の導入 (英語) というタイトルのブログ投稿を参照してください。

接続リスナーとチャネルリスナー

接続ファクトリは、ConnectionListener および ChannelListener 実装の登録をサポートしています。これにより、接続およびチャネル関連のイベントの通知を受け取ることができます。(ConnectionListener は、接続が確立されたときに宣言を実行するために RabbitAdmin によって使用されます。詳細については、交換、キュー、バインディングの自動宣言を参照してください)。次のリストは、ConnectionListener インターフェース定義を示しています。

@FunctionalInterface
public interface ConnectionListener {

    void onCreate(Connection connection);

    default void onClose(Connection connection) {
    }

    default void onShutDown(ShutdownSignalException signal) {
    }

}

バージョン 2.0 から、org.springframework.amqp.rabbit.connection.Connection オブジェクトに com.rabbitmq.client.BlockedListener インスタンスを指定して、接続のブロックおよびブロック解除のイベントを通知できるようになりました。次の例は、ChannelListener インターフェース定義を示しています。

@FunctionalInterface
public interface ChannelListener {

    void onCreate(Channel channel, boolean transactional);

    default void onShutDown(ShutdownSignalException signal) {
    }

}

ChannelListener を登録するシナリオの 1 つについては、公開は非同期です — 成功と失敗を検出する方法を参照してください。

チャネルクローズイベントのロギング

バージョン 1.5 では、ユーザーがログレベルを制御できるようにするメカニズムが導入されました。

AbstractConnectionFactory は、デフォルトの戦略を使用して、チャネルの閉鎖を次のように記録します。

  • 通常のチャネルクローズ (200 OK) はログに記録されません。

  • パッシブキュー宣言の失敗によりチャネルが閉じられた場合、DEBUG レベルでログに記録されます。

  • 排他的コンシューマー条件により basic.consume が拒否されたためにチャネルが閉じられた場合、そのチャネルは DEBUG レベル (3.1 以降、以前は INFO) でログに記録されます。

  • その他はすべて ERROR レベルでログに記録されます。

この動作を変更するには、closeExceptionLogger プロパティでカスタム ConditionalExceptionLogger を CachingConnectionFactory に挿入します。

また、AbstractConnectionFactory.DefaultChannelCloseLogger が公開され、サブクラス化できるようになりました。

コンシューマーイベントも参照してください。

ランタイムキャッシュのプロパティ

バージョン 1.6 から始まった CachingConnectionFactory は、getCacheProperties() メソッドを通じてキャッシュ統計を提供するようになりました。これらの統計を使用してキャッシュを調整し、本番環境で最適化できます。例: ハイウォーターマークを使用して、キャッシュサイズを増やす必要があるかどうかを判断できます。キャッシュサイズと等しい場合は、さらに増やすことを検討してください。次の表に、CacheMode.CHANNEL のプロパティを示します。

表 1: CacheMode.CHANNEL のキャッシュプロパティ
プロパティ 意味
connectionName

ConnectionNameStrategy によって生成された接続の名前。

channelCacheSize

アイドル状態が許可されている現在構成されている最大チャネル数。

localPort

接続用のローカルポート (利用可能な場合)。これを使用して、RabbitMQ 管理 UI の接続とチャネルを関連付けることができます。

idleChannelsTx

現在アイドル状態 (キャッシュされている) のトランザクションチャネルの数。

idleChannelsNotTx

現在アイドル状態 (キャッシュされている) の非トランザクションチャネルの数。

idleChannelsTxHighWater

同時にアイドル (キャッシュ) されたトランザクションチャネルの最大数。

idleChannelsNotTxHighWater

最大数の非トランザクションチャネルが同時にアイドル (キャッシュ) されています。

次の表に、CacheMode.CONNECTION のプロパティを示します。

表 2: CacheMode.CONNECTION のキャッシュプロパティ
プロパティ 意味
connectionName:<localPort>

ConnectionNameStrategy によって生成された接続の名前。

openConnections

ブローカーへの接続を表す接続オブジェクトの数。

channelCacheSize

アイドル状態が許可されている現在構成されている最大チャネル数。

connectionCacheSize

アイドル状態が許可される現在構成されている最大接続数。

idleConnections

現在アイドル状態の接続の数。

idleConnectionsHighWater

同時にアイドル状態になっている接続の最大数。

idleChannelsTx:<localPort>

この接続で現在アイドル状態 (キャッシュされている) のトランザクションチャネルの数。プロパティ名の localPort 部分を使用して、RabbitMQ 管理 UI の接続およびチャネルと関連付けることができます。

idleChannelsNotTx:<localPort>

この接続で現在アイドル状態 (キャッシュされている) の非トランザクションチャネルの数。プロパティ名の localPort 部分を使用して、RabbitMQ 管理 UI の接続およびチャネルと関連付けることができます。

idleChannelsTxHighWater:<localPort>

同時にアイドル (キャッシュ) されたトランザクションチャネルの最大数。プロパティ名の localPort 部分を使用して、RabbitMQ 管理 UI の接続とチャネルを関連付けることができます。

idleChannelsNotTxHighWater:<localPort>

最大数の非トランザクションチャネルが同時にアイドル (キャッシュ) されています。プロパティ名の localPort 部分を使用して、RabbitMQ 管理 UI の接続およびチャネルと関連付けることができます。

cacheMode プロパティ (CHANNEL または CONNECTION) も含まれます。

cacheStats
図 1: JVisualVM の例

RabbitMQ 自動接続 / トポロジリカバリ

Spring AMQP の最初のバージョン以降、フレームワークは、ブローカーに障害が発生した場合に独自の接続とチャネルの回復を提供してきました。また、ブローカーの構成に従って、接続が再確立されると、RabbitAdmin はすべてのインフラストラクチャ Bean (キューなど) を再宣言します。現在 amqp-client ライブラリによって提供されている自動回復 (英語) には依存しません。amqp-client では、デフォルトで自動回復が有効になっています。2 つの回復メカニズムの間にはいくつかの非互換性があるため、デフォルトでは、Spring は基になる RabbitMQ connectionFactory の automaticRecoveryEnabled プロパティを false に設定します。プロパティが true であっても、Spring は回復した接続をすぐに閉じることにより、効果的に無効にします。

デフォルトでは、Bean として定義されている要素 (キュー、エクスチェンジ、バインディング) のみが、接続の失敗後に再宣言されます。その動作を変更する方法については、自動削除宣言の回復を参照してください。