コンテキスト: Netty 3.6.3.Final、Java 1.7、Scala 2.9.x
(おそらくアイドル状態の) スレッドの数を最小限に抑えるために、NIO クライアント/サーバーとワーカー プールを、異なる NIO ソケット チャネル ファクトリ (TCP) と 1 つの NioDatagramChannelFactory で共有したいと考えています。私は少なくとも 2 つ (または Finagle スタックでは 3 つ) のサーバー/クライアント ブートストラップ セットを使用しており、それぞれに独自の NIO ソケット チャネル ファクトリがあります。すべてのボスとワーカープールに新しいキャッシュされたスレッドプールを使用すると、ほとんどの場合使用されないスレッドの負荷が発生します。大まかな目標は、すべてのブートストラップ/チャネル ファクトリのワーカー数を 2 * CPU コア数に制限し、ボスの数を CPU コア数に制限することです。
自分のブートストラップ セットの 1 つとして、NioServer/ClientBossPool と NioWorkerPool に切り替えようとしています。ただし、基になる ThreadPoolExecutor の構成によっては、ブートストラップをシャットダウンすると、メイン スレッドが AbstractNioSelector シャットダウン ラッチで永久に待機することになります。
class NioClientBossPoolTest {
@Test def shutdown() {
val corePoolSize = 1
val maxPoolSize = Integer.MAX_VALUE
val keepAliveSeconds = 60
val keepAliveUnit = TimeUnit.SECONDS
val blocking = true
val queue: BlockingQueue[Runnable] =
if(blocking) new LinkedBlockingQueue[Runnable](Integer.MAX_VALUE)
else new SynchronousQueue[Runnable]()
val executor = new ThreadPoolExecutor(corePoolSize,
maxPoolSize,
keepAliveSeconds,
keepAliveUnit,
queue)
val clientBossPool = new NioClientBossPool(executor, 1) // B
new NioServerBossPool(executor, 1) // C
val workerPool = new NioWorkerPool(executor, 1) // A
val channelFactory = new NioClientSocketChannelFactory(clientBossPool, workerPool)
val bootstrap = new ClientBootstrap(channelFactory)
// hangs waiting for shutdown latch in AbstractNioSelector (NioWorker or NioClientBoss
// depending on the order of statement A, B, C) for
// LinkedBlockingQueue, corePoolSize = 1 and sequence of statements A, B and C other than [B, A, C]
// LinkedBlockingQueue, corePoolSize = 2 and sequence of statements A, B and C other than
// [A, B, C], [B, C, A] and [C, B, A]
bootstrap.shutdown()
}
}
エグゼキュータ サービスの構成がいくつかの特定の要件を満たす必要があることは確かですが、どれ (コア プール サイズ、キュー タイプ) ですか? bootstrap.shutdown() は、ステートメント A、B、および C の実行順序が正確に [B, A, C] である場合を除き、永久にブロックされます。3 つのステートメントの 6 つの組み合わせのうち 3 つについて、コア プール サイズを 2 ブロックに増やします。コア プール サイズが 2 を超える場合、または SynchronousQueue を使用する場合、各組み合わせは終了します。