アイドル状態の非同期コンシューマーの検出

効率的ですが、非同期コンシューマーの問題の 1 つは、アイドル状態を検出することです。ユーザーは、一定期間メッセージが届かない場合に何らかのアクションを実行する必要がある場合があります。

バージョン 1.6 から、メッセージが配信されずに時間が経過したときに ListenerContainerIdleEvent を発行するようにリスナーコンテナーを構成できるようになりました。コンテナーがアイドル状態の間、idleEventInterval ミリ秒ごとにイベントが発行されます。

この機能を構成するには、コンテナーで idleEventInterval を設定します。次の例は、XML および Java でこれを行う方法を示しています ( SimpleMessageListenerContainer と SimpleRabbitListenerContainerFactory の両方に対して)。

<rabbit:listener-container connection-factory="connectionFactory"
        ...
        idle-event-interval="60000"
        ...
        >
    <rabbit:listener id="container1" queue-names="foo" ref="myListener" method="handle" />
</rabbit:listener-container>
@Bean
public SimpleMessageListenerContainer(ConnectionFactory connectionFactory) {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
    ...
    container.setIdleEventInterval(60000L);
    ...
    return container;
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(rabbitConnectionFactory());
    factory.setIdleEventInterval(60000L);
    ...
    return factory;
}

いずれの場合も、コンテナーがアイドル状態のときにイベントが 1 分に 1 回公開されます。

イベントの消費

ApplicationListener — 一般的なリスナー、またはこの特定のイベントのみを受信するように絞り込まれたものを実装することで、アイドルイベントをキャプチャーできます。Spring Framework 4.2 で導入された @EventListener も使用できます。

次の例では、@RabbitListener と @EventListener を 1 つのクラスに結合します。アプリケーションリスナーはすべてのコンテナーのイベントを取得することを理解する必要があるため、アイドル状態のコンテナーに基づいて特定のアクションを実行する場合は、リスナー ID を確認する必要がある場合があります。この目的で @EventListenercondition を使用することもできます。

イベントには次の 4 つのプロパティがあります。

  • source: リスナーコンテナーインスタンス

  • id: リスナー ID (またはコンテナー Bean 名)

  • idleTime: イベントが公開されたときにコンテナーがアイドル状態だった時間

  • queueNames: コンテナーがリッスンするキューの名前

次の例は、@RabbitListener アノテーションと @EventListener アノテーションの両方を使用してリスナーを作成する方法を示しています。

public class Listener {

    @RabbitListener(id="someId", queues="#{queue.name}")
    public String listen(String foo) {
        return foo.toUpperCase();
    }

    @EventListener(condition = "event.listenerId == 'someId'")
    public void onApplicationEvent(ListenerContainerIdleEvent event) {
        ...
    }

}
イベントリスナーは、すべてのコンテナーのイベントを表示します。前の例では、リスナー ID に基づいて受信したイベントを絞り込みます。
アイドルイベントを使用してリスターコンテナーを停止する場合は、リスナーを呼び出すスレッドで container.stop() を呼び出さないでください。これを行うと、常に遅延と不要なログメッセージが発生します。代わりに、コンテナーを停止できる別のスレッドにイベントを渡す必要があります。