32

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 を実行していますが、10,000select接続のアプリケーションで CPU 時間の 90% もの高さをまだ取っています。

MINA 2.0.4 を使用しているため、この関連するバグは修正されています。

4

4 に答える 4

18

残念ながら、これは数字の間違った解釈です。

私は何度もこの状況に直面しました (また、 stackoverflowについても質問します)。

主な理由は、VisualVM が正しい CPU 時間を表示しないことです。状態のスレッド時間のパーセンテージを示していますRUNNING。しかし、ドキュメントからThread.State

実行可能なスレッドのスレッド状態。実行可能状態のスレッドは Java 仮想マシンで実行されています が、プロセッサなどのオペレーティング システムからの他のリソースを待機している可能性があります。

これはまさに起こっていることです。実際には、スレッドは OSepoll_wait()呼び出し内でブロックされています。Linux ボックスでは、それが事実であることを確認する方法がいくつかあります。

strace'ingスレッド

$ strace -tttT -f -p [thread-id]

jstack出力からスレッド ID を取得できます。

$ 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スレッド

$ pidstat -tu -p [java-pid] | grep [thread pid]

このスレッドでは、システムの CPU 時間とユーザーの CPU 時間が低下していることがわかります。つまり、CPU を消費していません。

スレッド状態のポーリングps

$ ps -eL -o pid,tid,state | grep [thread-id]

Sほとんどの場合Sl、(runnable) ではなく (interruptible sleep)状態のスレッドが表示されますR

最終的に、サービスに運用上の問題がなければ、それについて心配する必要はありません。

于 2016-05-25T10:31:40.950 に答える
1

1 つのアプリが 10,000 の接続をポーリングしており、接続ごとにほとんど CPU を使用していませんが、すべてを合わせると CPU 時間のかなりの部分になる可能性があります。すべての優先順位は、他のジョブを最初に整列させることです。

接続数は少ないが、接続ごとのクランチが多い他のアプリも高い割合を示す可能性がありますが、待機時間の割合は低く、CPU 使用率は高くなるはずです。

于 2013-12-09T18:43:17.363 に答える