以下の Spring Integration doc の 7.1.7 Asynchronous polling セクションでは、Poller と TaskExecutor が調整されていない場合にメモリ リークが発生する可能性があると説明されています。しかし、私はそれを理解していませんでした。
<int:service-activator input-channel="publishChannel" ref="myService">
<int:poller receive-timeout="5000" task-executor="taskExecutor" fixed-rate="50"/>
</int:service-activator>
<task:executor id="taskExecutor" pool-size="20" queue-capacity="20"/>
上記の構成は、調整されていない構成の 1 つを示しています。
すべてのスレッドがブロックされ、新しいメッセージが到着するか、タイムアウトが期限切れになるのを待っている場合でも、ポーラーは新しいタスクをスケジュールし続けます。5 秒のタイムアウトでタスクを実行する 20 のスレッドがあるとすると、それらは 1 秒あたり 4 の割合で実行されます (5000/20 = 250 ミリ秒)。ただし、新しいタスクは 1 秒あたり 20 の割合でスケジュールされているため、タスク エグゼキューターの内部キューは (プロセスがアイドル状態の間) 1 秒あたり 16 の割合で増加するため、基本的にメモリ リークが発生します。
これを処理する方法の 1 つは、Task Executor の queue-capacity 属性を 0 に設定することです。
誰か詳しく教えてください。
上記のコードに対する私の理解は次のとおりです。
pool-size は 20 であるため、20 個のスレッドが実行されます。
receive-timeout は 5 秒です。したがって、タスクを完了するために 20 のスレッドに 5 秒が与えられます。
固定レートは 50 ミリ秒です。したがって、新しいタスクは 1 秒あたり 20 のレートでスケジュールされます。
いくつか質問があります:
Q. 20 スレッドの実行に 5 秒以上かかるとどうなりますか?
Q. ドキュメントでは、前述のタスクは 1 秒あたり 4 つの割合で実行されます。ただし、4 秒未満で実行されるタスクもあれば、それ以上かかるタスクもあります。
Q. メモリ リークはどのように発生しますか? 使用可能なスレッドとキューがない場合、Executor は代わりに拒否ポリシーに従ってそれを拒否します。
Q. queue-capacity を 0 に設定すると、どのように役立ちますか? 私の理解によると、すべてのスレッドがビジーである場合、エグゼキューターはキュー容量に達するまでそれらをキューに入れます。