スタック分析-サーバーの問題の場所

1.一般的なサーバーの問題の場所:

1.一般的なサーバーの問題:

日常の開発では、一般的なサーバーの問題は次のカテゴリに分類できます。

  • CPU過負荷の問題
  • 高メモリの問題
  • ディスクIOの問題
  • ネット障害

2.サーバーの問題の場所の一般的な考え方:

サーバーに問題がある場合は、通常、次のアイデアに従ってサーバーを特定できます。

  • ①最近リリースされたバージョンの場合は、まずコード提出記録から最新バージョンのコードに問題がないか分析してください。
  • ②ps、top、その他のコマンドを使用して、スレッドのステータスを分析します
  • ③まず異常サーバーをオフラインにしてサーバー環境を維持し、次にjstackを使用してスレッドスナップショット情報をエクスポートし、jmapを使用して分析のためにスタックメモリログをエクスポートします。このコマンドはオンラインサーバーのパフォーマンスに影響するため、サーバーは以前にオフラインになっています。ユーザーへの影響を防ぐための実行

        ディスクIOの問題とネットワークの問題については、通常は迅速に特定できるため、この記事では説明しません。ここでは、主に、CPUとJavaのメモリ使用量が多い問題を特定して解決する方法を紹介します。

第二に、CPUの急上昇の問題のポジショニング:

1. JavaでのCPUを集中的に使用する操作は何ですか?

  • 頻繁なGC:アクセスボリュームが大きく、メモリ割り当てが速すぎると、頻繁なGCまたはFGCが発生し、CPUが急上昇する可能性があります。
  • スレッドコンテキストの切り替え:多数のスレッドの状態が、ブロック(ロック待機、IO待機など)と実行の間で変化します。これは、ロックの競合が多い場合に簡単に発生する可能性があります。
  • 一部のスレッドは、無限ループなどの非ブロッキング操作を実行しています
  • シリアル化および逆シリアル化
  • 正規表現

2. JavaプログラムCPUの急上昇ポジショニング手順:

(1)topコマンドを使用して、CPUを最も消費するスレッドIDを見つけます。

top –hp PID

(2)スレッドスナップショットファイルのスレッド番号は16進数で記録されるため、CPUを最も消費するスレッドIDを16進数に変換します。

printf'%x \ n'PID

(3)問題のサーバーをオフラインにしてから、jstackを使用してスレッドスナップショット情報をエクスポートし、手順(2)で見つかったスレッドIDが何をしているかを確認します。

jstackpid|グリップ時間-A30

        この時点で、異常なスレッドが実行している操作の種類を特定し、問題に対処するための具体的な解決策を講じることができます。

第三に、Javaメモリ使用量のポジショニング方法が高すぎます。

        高メモリは通常、メモリリークとメモリオーバーフローが原因で発生します。最初にスレッドスナップショットログが異常であるかどうかを確認し、次にjmap -dumpを使用してスタックログをエクスポートし、どのオブジェクトがスペースを占有しているかを確認します。これは多くの場合、コードの誤操作または不正確な操作が原因であり、作成されたスレッドが多すぎる可能性があります。につながる

スタックログのエクスポート:jmap -dump:format = b、file = filename [pid]

次に、IBMHeapAnalyzerまたはEclipseMemoryAnalyzerを使用して分析します

第4に、jstackスレッドスナップショットファイル分析の説明:

4.1.スレッドスナップショットステータススタックトレース説明:

4.1.1、デッドロック:デッドロックスレッド。複数のスレッドが互いにリソースを占有し、常に互いに待機し、ブロッキングにつながる状況。

4.1.2、実行可能:スレッドにすべての実行条件、または実行中のスレッド状態があることを示します

4.1.3。モニターエントリの待機とObject.wait():モニターは、スレッドの相互排除と協調を実現するためのJavaの同期ロックメカニズムの主な手段です。オブジェクトまたはクラスロックと見なすことができます。各オブジェクトには1つあります。ロックは1つだけです。モニター、各モニターは同時に1つのスレッドのみが所有でき、スレッドは「アクティブスレッド」、他のスレッドは「待機中のスレッド」、「待機中のスレッド」は2つのセット「EntrySet」に格納されます待機中の「WaitSet」。「EntrySet」で待機しているスレッド状態は「Waitingformonitorentry」であり、「WaitSet」で待機しているスレッド状態は「inObject.wait()」です。同期によって保護されているコードセグメントはクリティカルセクションです。スレッドがクリティカルセクションに入るために適用されると、「EntrySet」キューに入ります。スレッドがモニターを取得してクリティカルセクションに入ると、実行を継続するスレッドが満たされない場合、オブジェクトのwait()メソッドを呼び出し、Monitorを放棄して、「WaitSet」キューに入ります。他のスレッドがオブジェクトでnotify()またはnotifyAll()を呼び出す場合にのみ、 「WaitSet」キューは、競争に参加する機会を得ます。

4.1.4、条件で待機:リソースを待機するか、特定の条件が発生するのを待機します。これは、スタックトレースと組み合わせて分析する必要があります。

(1)最も一般的なのは、スレッドがスリープ状態にあり、ウェイクアップを待機していることです。

(2)一般的な状況は、ネットワークIOを待機することです。NIOが導入される前に、ネットワーク接続ごとに、ネットワークの読み取りおよび書き込み操作を処理する対応するスレッドがあります。読み取りおよび書き込み可能なデータがない場合でも、スレッドは引き続き存在します。読み取りおよび書き込み操作でブロックされます。NIOの導入後、ネットワークで多数のスレッドがブロックされていることがわかった場合、ネットワークのブロックによってスレッドの実行が妨げられるため、ネットワークのボトルネックの兆候である可能性があります。

  • 1つの状況は、ネットワークが非常にビジーで、ほとんどすべての帯域幅を消費し、ネットワークの読み取りと書き込みを待機しているデータがまだたくさんあることです。
  • 別の状況としては、ネットワークがアイドル状態であるが、ルーティングなどの問題により、パケットが正常に到着できない場合があります。

4.1.5.ブロック:スレッドのブロックとは、現在のスレッドの実行中に、必要なリソースが長時間待機しているが取得されておらず、コンテナーのスレッドマネージャーによってブロック済みとしてマークされていることを意味します。リソースのタイムアウトを待機しているスレッドとして理解されます。

4.2.スレッドスナップショットファイルで注意が必要な現象:

(1)継続的に実行可能なIOスレッド:

        IO操作は、データベースのデッドロック、ネットワークの読み取りと書き込みなどのRUNNABLE状態でブロックされる可能性があるため、IOスレッドの実際の状態の分析に特別な注意を払う必要があります。一般的に、RUNNABLEでキャプチャされたIO呼び出しには問題があります。

        次のスタックは次のことを示しています。スレッドの状態はRUNNABLEであり、呼び出しスタックはSocketInputStreamまたはSocketImpl、socketRead0およびその他のメソッド上にあります。コールスタックにはjdbc関連のパッケージが含まれており、データベースのデッドロックが発生する可能性があります

"d&a-614" daemon prio=6 tid=0x0000000022f1f000 nid=0x37c8 runnable
[0x0000000027cbd000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at oracle.net.ns.Packet.receive(Packet.java:240)
at oracle.net.ns.DataPacket.receive(DataPacket.java:92)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:172)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:117)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1034)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:588)

次のスタックは、スレッドプールの場合です。

"http-bio-8082-exec-3858" #50615 daemon prio=5 os_prio=0 tid=0x00007f7cc002f800 nid=0xc5c0 runnable [0x00007f7c34659000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:516)
	at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501)
	at org.apache.coyote.http11.Http11Processor.setRequestLineReadTimeout(Http11Processor.java:167)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:946)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
	- locked <0x0000000093db7ce8> (a org.apache.tomcat.util.net.SocketWrapper)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

(2)デッドロック現象:

        jstackは、直接特定できるデッドロック状況の分析に役立ち、特定の状況を分析および処理できます。

(3)無限ループ:

        無限ループ状態の兆候は、CPUが急上昇し、スレッドの実行ステータスをチェックしてスレッドを見つけ、CPU実行時間セグメントと高いCPU使用率に長い時間がかかり、スレッドスタックログを出力して、スレッドは実行可能状態になっています

実行可能状態

(4)スレッドコンテキストの切り替えが頻繁すぎる:

①JVMにはスレッドスケジューラがあり、どのスレッドをいつ実行するかを決定するために使用されます。スケジューラには、プリエンプティブスレッドスケジューラと協調スレッドスケジューラの2つの主要なタイプがあります。各スレッドには独自の優先度がありますが、優先度は、優先度の高いスレッドがスケジュールされることを意味するのではなく、CPUによってランダムに選択されます。

  • プリエンプティブスレッドスケジューリング:スレッドが独自のタスクを実行しているとき、タスクは完了していませんが、CPUはスレッドを強制的に一時停止し、他のスレッドがCPUを使用する権利を占有できるようにします。
  • 協調スレッドスケジューリング:スレッドが独自のタスクを実行しているとき、途中で中断することはできません。現在のスレッドがタスクの実行を完了するのを待ってからCPUの所有権を解放する必要があり、他のスレッドはCPU。

②この種の問題の兆候は、CPUとメモリがすべて急上昇し、スレッドの実行スケジューリング調整がCPUによって処理されるため、jstackに待機中のtimed_waiting状態のスレッドが多数存在することです。 、およびCPUは、実行可能セグメントを各スレッドに割り当てる責任があります。これらのスレッドスケジューリングを頻繁に処理すると、CPUの負荷が高くなりすぎます。

(5)多数のGCスレッド:

        このタイプの問題の兆候は、jstackに多数のGCスレッドがあり、GCスレッドが最も高いCPUを消費することです。これは、頻繁なGCと呼ばれることがよくあります。

jstatコマンドは、ヒープメモリのさまざまな部分の使用状況とロードされたクラスの数を表示できます。コマンドの形式は次のとおりです。

jstat[-コマンドオプション][vmid][間隔時間/ミリ秒][クエリ数]

root @ 8d36124607a0:/#jstat -gcutil 9 1000 10
  S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
  0.00 0.00 0.00 75.07 59.09 59.60 3259 0.919 6517 7.715 8.635
  0.00 0.00 0.00 0.08 59.09 59.60 3306 0.930 6611 7.822 8.752
  0.00 0.00 0.00 0.08 59.09 59.60 0.943 6701 7.924 8.867
  0.00 0.00 0.00 0.08 59.09 59.60 3397 0.955 6793 8.029 8.984

おすすめ

転載: blog.csdn.net/a745233700/article/details/122660058