Javaアプリケーションスレッドの漏洩処理を一度メモする


Javaアプリケーションでは、メモリの漏洩やOOMの場合が多く、スレッドの漏洩は初めてです.もちろん、スレッドプールを使用することは、スレッドを自分で作成する方法ではなく、スレッドを管理することに大きなメリットがあります.
SecureCRTを通じてあるシステムのテスト環境にログインすることができず、リソースが割り当てられていないことを示すテストが見つかりました.そこで試してみると、このJavaアプリを導入したアカウントでは確かにログインできませんが、別のアカウントでログインできます.サーバーに「cannot create native thread」と印刷し続けるエラーログがあり、ついでにトップを押すと、サーバーLoadは普段より少し高くなっていることがわかります.
エラーログから見ると、Javaアプリケーションはサーバにスレッドを作成するように要求したが、サーバはリソース制限のため提供できなかったため、アプリケーションはこのエラーログを印刷した.自分YY了下:サーバーのリソースが確かに不足している可能性があります.このサーバーには他のアプリケーションも配置されているからです.アプリケーションが作成したスレッドが多すぎるかもしれません.非配置アカウントでサーバにログインでき、会社のサーバ構成はまあまあなので、すぐに最初の疑いを放棄し、2番目の推測かどうかを検証し始めました.
このJavaアプリケーションで作成されたスレッドの数を見てみると、見ていないと分からないので、びっくりして1023個のスレッドが作成されていました.Javaアプリケーションが作成したスレッドの数を表示するには、ps+grepやjpsなどでjavaアプリケーションのpidを取得する3つの方法があります.
ps -Tfp <pid> cat /proc/<pid>/stat | awk '{print $20}' ls /proc/<pid>/task | wc

このアプリケーション自体はよく知られているので、通常の状況ではラインオフの数は基本的に450前後で、1023は間違いなく異常な状況なので、心の中では基本的に一部のスレッドが暴走しています.ついでにulimit-aを見てみるとmax user processesが1024に設定されていることがわかりました.この値は確かに少し小さいとはいえ、生産環境ではこのような小さな値を設定することはほとんど不可能です.しかし、テスト環境では、この比較的小さな値が問題を露呈しているため、設定が大きくなれば、問題を露呈するには長い時間がかかると推定されています.
この時点でこのJavaアプリケーションを導入したadminアカウントが最大スレッドに達しているため、SecureCRTでリモートログインすることはできません.この時、rootアカウントを探してthread dumpを作ることができるはずですが、問題は基本的に分かります.その結果、テスト衝動に駆られてrootにサーバーを再起動させたが、環境が変わっていないので、しばらく走ってから問題が浮かび上がった.もちろん、システムが熟知していれば、thread dumpだけで基本的に問題の所在を特定することができます.システムがあまり熟知していない場合は、異なる時点でthread dumpをして、発生した主なスレッドが何なのかを分析しやすいことを覚えておいてください.
Thread Dumpの後、問題があまりにも明らかであれば、dumpログを見てみると基本的に発見できます.状況が複雑な場合は、TDAというツールを試してみてください.各ステータススレッドの数と、さまざまなタイプのスレッドの数を見ることができます.さらに,複数のdump間のスレッドの変化を比較することができ,これは比較的複雑な場合に非常に役立つ.
このcaseに戻ると、原因は簡単です.アプリケーションには、サードパーティ企業とのクライアント長接続スレッドが動的に多数作成され、双方がメッセージを送信し、同時トラフィック統計と制御を行うために、このクライアントスレッドには、タイミングクリアカウントのためのスレッドが作成されます.バックグラウンドでは、各クライアントスレッドの実行状況をタイミングタスクで検出し、クライアントスレッドが異常に終了すると、そのタイミング検出タスクは、対応するクライアントスレッドのインスタンスでnew Thread(Runnable)を再newし、startを起動します.問題はクライアントスレッドが異常に終了した処理でfinallyでクライアントスレッドを終了しただけで、クリアカウントのサブスレッドは処理されず、バックグラウンドタイミングタスクがクライアントを再起動するとクリアカウントのサブスレッドが再作成されます.テスト環境が不安定で、クライアントスレッドの基数が大きく、異常な終了が続く場合、バックグラウンドでクライアント状態を検出するタイミングタスクは、これらのクライアントスレッドを大量に再起動し、終了せず、制御されていないクリアカウントのサブスレッドを大量に生成する.
原因が分かって、問題も比較的に簡単で、具体的な処理方法は言いません.