netstatではなくlsofによって検出されたソケット


19

明らかにソケットを開くことにより、ファイル記述子が不足しているアプリケーションがありますが、これらのソケットが何をするのか正確にはわかりません。これらは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 FAQgrep $SOCKET /proc/net推奨されているように、$ SOCKETがたとえば263746679のように 実行しようとしましたが、結果も得られませんでした。


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


また、最近、.NET Core Webアプリ(Kestrelを使用するUbuntuサーバー)でこの問題に直面していますが、記録されたデバイスは「protocol:TCP」という名前の「0,9」です。デバイス0と9が何であるかを正確に見つけようとすることは難しいことがわかっています。しかし、すべての症状は、バインドせずにソケットを開いて使用した場合と同じように見えます。
アイスラバ

回答:


17

これは、ソケットを作成しても、connect()またはbind()を使用しないで発生する可能性があります。最善の策は、アプリケーションをトレース(-fF)してから、lsofの出力と相互参照して、問題の原因となっているソケットを判別することです。デバッグのボーナス方法として:ソケットコールをデバッグ情報でラップし、/ dev / nullに書き込むと、誇大なログファイルを表示せずにstraceに表示されます。


おかげで、これは面白いですね。それが実際にアプリケーションに当てはまるかどうかを確認しようとします。
ロバートムンテアヌ

1
これはJavaなので、straceを使用するのは非常に難しい可能性があります。より良い方法は、親(実際の)JDKソケットに渡す前に情報を記録する独自のソケットサブクラスを作成することです。straceは、OSへの基礎となるJava呼び出しのみを見ることができ、実際にそれらのソケット呼び出しを行っているものをスレッド内で見ることはできません。
トロイエンゲル

@troyengel:Byteman(jboss.org/byteman)を、これらの呼び出しをトレースするために必要なバイトコードを注入できる非常にきれいなツールを(再)発見しました。
ロバートムンテアヌ

最も有用な答えなので、これは報奨金を受け取ります。ありがとう!
ロバートムンテアヌ

2

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

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

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

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

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


1

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

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

次に、システムが最新であることを確認します。これには、すべてのライブラリとサーバーが含まれます。Javaアプリケーションサーバーが古くなっている可能性があります(使用している場合)。また、アプリケーションサーバーが正しく構成されていない可能性もあります。構成ファイルを確認しconnectionTimeout、/またはを下げる必要がありますmaxKeepAliveRequests(どのアプリケーションサーバーを使用しているか、まったく使用していないかはわかりません...)。

このアプリケーションが何をするのかはわかりませんが、数万のソケットが必要だと思わない場合、これはほとんど間違いなくJavaアプリケーションの「ファイル記述子リーク」です。ベンダーにバグレポートを送信する必要がある場合があります。このバグレポートには、問題の再現方法に関する情報を含める必要があります。

問題をデバッグするいくつかの方法を次に示します。

Wireshark(またはCLIの場合はtwireshark)は、これらのソケットがどのように使用されているかを確認するのに最適なツールです。Wiresharkを使用すると、ネットワーク上で発生しているトラフィックの種類を分類できます。最初のいくつかの接続が成功し、ファイル記述子の制限に達する可能性があります。ファイル記述子の制限に達すると、Wiresharkは何も拾いません(そして、この問題に関してはneaterはnetstatです)が、これは問題を絞り込むのに役立ちます。多くの発信SYNが送信されている場合がありますが、SYN / ACKは受信されていないため、多くのtcp接続がSYN_WAIT状態のままになっています。

ソースコードにアクセスでき、作成されるソケットのタイプ(straceの使用やコードの検索など)がわかっている場合は、Eclipse(または別のIDE)でプロジェクトを開き、次の関数にブレークポイントを設定できます。これらのソケットを作成しています。ブレークポイントにヒットすると、スタックトレースを確認できます。このファイル記述子のリークは、単純な無限ループか、ソケットタイムアウト値が大きすぎる可能性があります。もう1つの可能性はsocket.close()、接続をクリーンアップするためにJavaアプリが実行していないことです。クローズは通常、aのfinelyブロックで行われtry/catchます(はい、ソケットはJavaで常にtry / catchを持たなければなりません。そうしないと、ビルドされません:)。結局のところ、JavaアプリがIOExceptionを適切に処理していない可能性があります。


答えてくれてありがとう。実際に管理しているのではなく、実際にこのアプリケーション(コンテナパーツ)を開発しています。ソケットが閉じられないことに関連する問題を見つけることができませんでした。しかし、wireshark / twiresharkのヒントは良いので、それを使用します。
ロバートムンテアヌ

@Robert Munteanuこのアプリを構築している場合、これはstackoverflowの質問です。あまりにも多くのソケットを開いている場合でも。
ルーク

ルーク:これをコードごとに見つけるのをあきらめ、システム管理者として追跡しようとしました。それが私がSFに投稿した理由です。そして、はい、私はどういうわけか開いているソケットが多すぎることを知っています。しかしようにゼロ手がかりがあります...
ロバートムンテアヌ

@Robert Munteanuソケットの作成時にブレークポイントを設定し、そのポイントでスタックトレースとメモリを確認する必要があります。あなたは無限ループに陥っていると思う。あなたのコードがこのような複雑な問題に対する最良のアプローチになるとはいえ、あらゆる変数を見てステップできること。
ルーク

残念ながら、これは20のサーバーのいずれかでランダムに発生します-常に同じではありません-、実稼働環境でのみ、おそらく週に2回。それ以外の場合は、指で触れるのはかなり簡単でした。現在、Byteman(jboss.org/byteman)を使用して、ソケットの作成/バインド/接続/クローズの呼び出しを追跡しています。うまくいけば何かが出てくるでしょう。
ロバートムンテアヌ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.