web-dev-qa-db-ja.com

Spring AMQPリスナーコンテナの同時実行性はどのように実装されていますか?

私のコンテナXML設定:

<rabbit:listener-container
        connection-factory="myConnectionFactory"
        acknowledge="none"
        concurrency="10"
        requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
</rabbit:listener-container>

myListenerは単なるクラスです

@Component("myListener")
public class MyListener implements MessageListener {
    @Autowired
    SomeDependency dependency;
    ....
}

XMLでconcurrency="10"を指定しました。これはどういう意味ですか正確に


私は見つけました いくつかのドキュメント 。それらは、次のように述べるのにそれほど役立ちません。

作成する同時コンシューマーの数を指定します。デフォルトは1です。


私が興味を持っているのは、MyListenerがスレッドセーフである必要があるかどうかです。

  • 多くのインスタンスが作成されていますか、それとも単一のインスタンスが多くのスレッドで使用されていますか?
  • 同期なしでインスタンスフィールドにアクセスできますか?
  • SomeDependency dependencyは1回インスタンス化されますか、それともスレッド/インスタンスごとにインスタンス化されますか?
  • dependencyはスレッドセーフである必要がありますか?
16
Parobay

はい、並行性を使用するには、リスナーがスレッドセーフである必要があります。コンテナごとに1つのリスナーインスタンスがあります。ただし、_<rabbit:listener-container/>_名前空間要素は、実際には「共有」属性を追加するための単なる便利なものであり、各リスナー要素は独自のコンテナーを取得します。

一般に、ステートレスオブジェクト(書き込まれるフィールドがない)を使用するのが最善ですが、それが常に可能であるとは限りません。

リスナーがスレッドセーフでない場合は、次を使用できます...

_<rabbit:listener-container
    connection-factory="myConnectionFactory"
    acknowledge="none"
    requeue-rejected="false">
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    <rabbit:listener ref="myListener" queues="myQueue"/>
    ...
</rabbit:listener-container>
_

...そして@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)を追加します。次に、リスナーごとにコンテナーを取得し、リスナーの異なるインスタンスがそれぞれに注入されます。

また、リスナーに挿入されたスレッドセーフではない依存関係のプロトタイプスコープも必要になります。

15
Gary Russell