どうやらソケットを開いたためにファイル記述子が不足しているアプリケーションがありますが、これらのソケットが何をしているのか正確にはわかりません。これらはlsof出力に次のように表示されます
Java 9689 appuser 1010u sock 0,5 263746675 can't identify protocol
Java 9689 appuser 1011u sock 0,5 263746676 can't identify protocol
Java 9689 appuser 1012u sock 0,5 263746677 can't identify protocol
Java 9689 appuser 1014u sock 0,5 263746678 can't identify protocol
Java 9689 appuser 1015u sock 0,5 263746679 can't identify protocol
Java 9689 appuser 1016u sock 0,5 263746681 can't identify protocol
/ proc/$ PID/fdとして
lrwx------ 1 appuser appuser 64 Jun 23 11:49 990 -> socket:[263732085]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 991 -> socket:[263732086]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 992 -> socket:[263735307]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 993 -> socket:[263732088]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 995 -> socket:[263735308]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 996 -> socket:[263735309]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 997 -> socket:[263745434]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 998 -> socket:[263745435]
lrwx------ 1 appuser appuser 64 Jun 23 11:49 999 -> socket:[263745436]
ただし、netstat -a
には同様の出力はありません。
これらのソケットとは何ですか?どのようにしてそれらが何をするのかを知ることができますか?
編集: lsof FAQ で推奨されているように、grep $SOCKET /proc/net
を実行してみました。$ SOCKETは、たとえば263746679、しかしそれも結果を与えませんでした。
背景として、アプリケーションは、とりわけネットワークコールを実行する複数のタスクのコンテナです。私は凶暴になるものを選び出す必要がありますが、それらのソケットが誰と通信するかを見つけるまで、私は立ち往生しています。
これは、ソケットを作成したが、connect()またはbind()を使用しない場合に発生する可能性があります。あなたの最善の策は、アプリケーションをstrace(-fF)し、lsofの出力と相互参照して、どのソケットが問題を引き起こしているかを特定することです。デバッグのボーナスメソッドとして:デバッグ情報でソケット呼び出しをラップし、それらを/ dev/nullに書き出すと、陽気に大きなログファイルを提供せずにstraceに表示されます。
Pythonを使用して、SSLソケットで同じ問題が発生しました。
解決策は、閉じる前にSSLレイヤーのラップを解除することでした。
これにより、アプリでソケットが適切に閉じます。
私が最初に行うことは、ファイル記述子の制限がある場合に増やすことです。
_~# vi /etc/sysctl.conf
fs.file-max = 331287
_
次に、システムが最新であることを確認します。これには、すべてのライブラリとサーバーが含まれます。 Javaアプリケーションサーバーが古い可能性があります(使用している場合)。アプリケーションサーバーが正しく構成されていない可能性もあります。構成ファイルを調べて、connectionTimeout
やmaxKeepAliveRequests
を下げる必要があります(使用しているアプリケーションサーバーの種類や、 1つを使用しています...)。
このアプリケーションの動作はわかりませんが、数万のソケットが必要だと思わない場合は、ほぼ間違いなく"file descriptor leak"がJavaにあります_ 応用。ベンダーにバグレポートを送信する必要がある場合があります。このバグレポートには、問題を再現する方法に関する情報を含める必要があります。
問題をデバッグするいくつかの方法を次に示します。
Wireshark(またはcliのtwireshark)は、これらのソケットがどのように使用されているかを確認するのに最適なツールです。 Wiresharkは、ネットワーク上でスローされるトラフィックの種類の内訳を提供します。最初のいくつかの接続が成功し、ファイル記述子の制限に達する可能性があります。ファイル記述子の制限に達すると、Wiresharkは何も拾いません(そして、その点ではnetstatが適切です)が、これは問題を絞り込むのに役立ちます。多くの発信SYNが送信されていても、SYN/ACKが受信されていないため、多数のTCP接続がSYN_WAIT状態のままになっている場合があります。
ソースコードにアクセスでき、作成されるソケットのタイプ(straceの使用やコードの検索など)がわかっている場合は、Eclipse(または別のIDE)でプロジェクトを開き、関数にブレークポイントを設定できます。これらのソケットを作成しています。ブレークポイントに到達すると、スタックトレースを確認できます。このファイル記述子のリークは、単純な無限ループであるか、ソケットのタイムアウト値が大きすぎる可能性があります。もう1つの可能性は、Javaアプリがsocket.close()
を使用して接続をクリーンアップしていないことです。クローズは通常、_try/catch
_のfinely
ブロックで行われます(はい、ソケットは常にJavaでtry/catchを実行する必要があります。そうしないとビルドできません:) 。結局のところ、JavaアプリがIOExceptionを適切に処理していない可能性があります。