MINAを使用するJavaアプリケーションがいくつかあり、それらすべてが20のMINAスレッドを使用しています。1つのアプリケーションが約10,000の同時接続を処理します。これらは通常アイドル状態ですが、時々入力を受け取ります。20はおそらくそのアプリケーションにとって妥当なスレッド数ですが、私はそれを正確にプロファイルしていません(この質問が出ています)。別のアプリケーションは、一度に約15の接続のみを処理しますが、IO作業を開始するため、非常にビジーであり、20のMINAスレッドがあり、明らかに多すぎます。
私にとって奇妙なのは、どちらのアプリケーションも、CPU時間の約30%、時には60%を、VisualVMでプロファイルされたMINAのselect()メソッドに費やしていることです。呼び出しスタックは次のようになります。
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:228)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:81)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
- locked <40ca5d54> (a sun.nio.ch.Util$2)
- locked <24649fe8> (a java.util.Collections$UnmodifiableSet)
- locked <3fae9662> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
at org.apache.mina.transport.socket.nio.NioProcessor.select(NioProcessor.java:72)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:1093)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
それは忙しい世論調査に基づいているようですが、それは私には本当に間違っているようです。
こんなに高い数字を見て心配する必要はありますか?何が原因ですか?それは私が最適化する必要があるものですか、それともスリープまたはアイドルルーチンに似ていますか?スリープルーチンのような場合は、他のCPUの作業よりも優先度が低くなるようにスケジュールされていますか?
更新:このスレッドは同じ問題のようです。私はそのアドバイスに従い、現在Java 1.7.0_45を実行select
していますが、接続が10kのアプリケーションでは、CPU時間の90%を占めることがわかります。
私たちはMINA 2.0.4を使用しています。つまり、この関連するバグは修正されています。
残念ながら、これは数値の誤った解釈です。
私はこの状況に何度も直面しました(そして、stackoverflowについても質問します)。
主な理由は、VisualVMが正しいCPU時間を表示しないためです。RUNNING
状態のスレッド時間の割合を示します。しかし、ドキュメントからThread.State
:
実行可能なスレッドのスレッド状態。実行可能状態のスレッドはJava仮想マシンで実行されていますが、プロセッサなどのオペレーティングシステムからの他のリソースを待機している可能性があります。
これはまさに起こっていることです。実際、OS epoll_wait()
呼び出し内でスレッドがブロックされています。Linuxボックスでは、それが事実であることを確認できるいくつかの方法があります。
strace
のスレッド$ strace -tttT -f -p [thread-id]
スレッドIDはjstack
出力から取得できます:
$ jstack [java-pid]
[...]
"Netty Builtin Server 1" #17 prio=5 os_prio=31 tid=0x00000001013dd800 nid=0xe12f runnable [0x0000700001fe4000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.KQueueArrayWrapper.kevent0(Native Method)
at sun.nio.ch.KQueueArrayWrapper.poll(KQueueArrayWrapper.java:198)
[...]
この場合、スレッドIDは0xe12f
(10進数に変換する必要があります)です。ほとんどの場合、スレッドがepoll_wait()
呼び出されます。
pidstat
ingスレッド$ pidstat -tu -p [java-pid] | grep [thread pid]
このスレッドにより、システムとユーザーのCPU時間が短くなることがわかります。つまり、CPUを消費しません。
ps
$ ps -eL -o pid,tid,state | grep [thread-id]
ほとんどの場合、スレッドは(実行可能)ではなく、状態S
またはSl
(割り込みR
可能なスリープ)で表示されます。
最後に、サービスに運用上の問題がない場合は、そのことについて心配する必要はありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加