web-dev-qa-db-ja.com

lsofによって検出されたがnetstatによって検出されなかったソケット

どうやらソケットを開いたためにファイル記述子が不足しているアプリケーションがありますが、これらのソケットが何をしているのか正確にはわかりません。これらは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、しかしそれも結果を与えませんでした。


背景として、アプリケーションは、とりわけネットワークコールを実行する複数のタスクのコンテナです。私は凶暴になるものを選び出す必要がありますが、それらのソケットが誰と通信するかを見つけるまで、私は立ち往生しています。

19
Robert Munteanu

これは、ソケットを作成したが、connect()またはbind()を使用しない場合に発生する可能性があります。あなたの最善の策は、アプリケーションをstrace(-fF)し、lsofの出力と相互参照して、どのソケットが問題を引き起こしているかを特定することです。デバッグのボーナスメソッドとして:デバッグ情報でソケット呼び出しをラップし、それらを/ dev/nullに書き出すと、陽気に大きなログファイルを提供せずにstraceに表示されます。

16
BMDan

Pythonを使用して、SSLソケットで同じ問題が発生しました。

  • Socket.close()を使用すると、ソケットが無期限にCLOSE_WAIT状態のままになる
  • socket.shutdown()を使用すると、lsofは「プロトコルを識別できません」と表示します

解決策は、閉じる前にSSLレイヤーのラップを解除することでした。

  • origsock = socket.unwrap()
  • origsock.close()

これにより、アプリでソケットが適切に閉じます。

2
user48134

私が最初に行うことは、ファイル記述子の制限がある場合に増やすことです。

_~# vi /etc/sysctl.conf
fs.file-max = 331287
_

次に、システムが最新であることを確認します。これには、すべてのライブラリとサーバーが含まれます。 Javaアプリケーションサーバーが古い可能性があります(使用している場合)。アプリケーションサーバーが正しく構成されていない可能性もあります。構成ファイルを調べて、connectionTimeoutmaxKeepAliveRequestsを下げる必要があります(使用しているアプリケーションサーバーの種類や、 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を適切に処理していない可能性があります。

1
Rook