2016-06-20 21 views
1

java7とtomcat7でWebアプリケーションを実行します。我々のアプリケーションでは、パフォーマンスが非常に急激に低下しました。平均応答時間は2倍になり、ピーク時には問題はさらに悪化しました。Javaデッドロックがパフォーマンスを低下させます

私たちはスレッドダンプを印刷して、状態のために永遠に待っているスレッドを見つけました。いくつかのスレッドダンプを行い、このスレッドの状態は決して変更されませんでした。 0x00007f868d817000と0x00007f868d817000にこのスレッドで

"logback-66215" daemon prio=10 tid=0x00007f86f4115800 nid=0x3758 waiting on condition [0x00007f868d817000] 
    java.lang.Thread.State: WAITING (parking) 
     at sun.misc.Unsafe.park(Native Method) 
     - parking to wait for <0x00007f8ddf241fa8> (a java.util.concurrent.SynchronousQueue$TransferStack) 
     at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) 
     at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458) 
     at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359) 
     at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925) 
     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
     at java.lang.Thread.run(Thread.java:745) 

参照は、スレッドダンプでは見つかりませんでした。

tomcatを再起動した後、スレッドはなくなり、パフォーマンスはそうだったようでした。

私たちは12コアのサーバー上で実行しています。私たちはCPU使用量を監視しますが、スパイクは見られませんでした。毎秒約500リクエストのためにピーク時にCPU使用率が800%に上がりましたが、最大でも1200%まで増加しませんでした。それが800%に達したときに増加が止まり、パフォーマンスの問題は本当に悪いものでした。

この状況を完全に理解するには、スレッディング、CPU、割り込みの内部について十分理解していません。私は本当にこの問題をより深いレベルで理解したいと思っています。

私の質問:誰かが私に説明することができます、なぜこのようなデッドロックが非常に問題を引き起こすのですか?なぜCPU使用率に表示されないので、完全にロードされたCPUが表示されますか?それとも、コンテクストの切り替えに関する問題でしょうか?

答えて

0

私が間違っていても上記のスレッドダンプとSynchronousQueueの存在に基づいて、私はCachedThreadPoolExecutor(Executors.newCachedThreadPool())を使っていくつかのタスクを実行していると思います。

したがって、ダンプはキャッシュされたスレッドの1つになります。ジョブがスレッドプールにエンキューされるのを待つだけです。ここには何も間違ってはいませんが、これはデッドロックではありません。実際のデッドロックは、とにかくスレッドダンプに明示的に述べられています。

CPU消費に関しては、WAITING状態に置かれたスレッドはCPUサイクルを消費せず、実行予定もありません。

あなたのパフォーマンスの問題はどこから発生していますか?

私があなただったら、サーバのすべてのメモリを食べることを意味していても、ジョブを実行するのに必要な数のスレッドを大量に作成するため、CachedThreadPoolの使用を避けたいと思います。そのスタックのための予約メモリ、少なくとも100k)とCPU(管理するスレッドが多すぎるとスケジューラが狂ってしまいます)。

大量のジョブが発生した場合のスレッドの最大数、サイズと種類、およびバックオフ戦略を選択できるように、(Executors.new*ファクトリを使用するのではなく)ThreadPoolExecutorを手動で構成することができます到来。

関連する問題