web-dev-qa-db-ja.com

ネットワーク接続からの読み取り時にプロセスが無期限にハングする

以下の更新:

別のデータセンターのDebian仮想マシンで、無関係なスクリプトで同様の問題が発生しました。

これは、説明されている問題 here のように疑わしく見えます(そして、その質問をしている人のように、サーバーの前にプロキシが設定されていません).

以下の説明との主な違いは、ハングしたプロセスにアタッチすると、recvfromではなくreadへの呼び出しが表示されることです。

$ strace -p 17527
Process 17527 attached - interrupt to quit
recvfrom(3, 

ただし、Pythonはプロキシされているという印象を受けていません。

>>> import os; print os.getenv("HTTP_PROXY"), os.getenv("http_proxy")
None, None

だから私はまだ困惑しています。残念ながら、リンクされた質問にも最終的な回答はありません。

(私は この質問 が関連しているかどうかも疑問に思っていますが、S3がConnection: closeヘッダーを尊重できない可能性は低いと思われます。)


いくつかのDebian(Wheezy、x86_64)サーバーがあり、すべて次の動作を示しています。

すべてのサーバーには、とりわけS3からデータをプルするcronジョブのセットがあります。これらは通常は正常に実行されますが、時折ps auxは、数時間または数日前に開始されたジョブの一部がまだ実行中であり、正常に終了していないことを明らかにします。

strace -p <pid>でそれらを検査すると、すべての場合で、プロセスは読み取りコマンドでハングします。たとえば、今チェックしたプロセスの出力は次のとおりです。

$ strace -p 12089
Process 12089 attached - interrupt to quit
read(5, 

開いているファイル記述子を確認すると、次のようになります。

$ Sudo lsof -i | grep 12089
python  12089    user    5u  IPv4 809917771      0t0  TCP my.server.net:35427->185-201.Amazon.com:https (ESTABLISHED)

最初はこれがPythonスクリプトでの読み取りタイムアウトの設定の不足によるものだと思っていましたが、いくつかの理由により、そうではないようです:

  1. これは、同じコードを使用して同じジョブがOS Xボックス(すべて10.5、i386)で実行されている場合には発生しません。
  2. 行うタイムアウトを設定するスクリプトの変形(socket.setdefaulttimeoutを使用して60秒のタイムアウト-これはPython 2.7、ただし、コードベースは2.5互換でなければなりません)は昨日からハングしています。
  3. Pythonではない別のプロセスが時々同様の動作を示すようです。この場合、Pythonスクリプトはsvn up --non-interactiveプロセスを実行しています( subprocess.Popen、それだけの価値があります)。

そのSVNプロセスの状況は似ています-

PythonはSVNを待っています:

$ strace -p 28034
Process 28034 attached - interrupt to quit   
wait4(28127, 

そしてSVNはread呼び出しが完了するのを待っています:

$ strace -p 28127
Process 28127 attached - interrupt to quit
read(6, 

そして、その読み取りは別の外部ホストを指しています:

$ Sudo lsof -i | grep 28127
svn     28127    user    3u  IPv4 701186417      0t0  TCP my.server.net:49299->sparrow.telecommunity.com:svn (ESTABLISHED)
svn     28127    user    6u  IPv4 701186439      0t0  TCP my.server.net:49309->sparrow.telecommunity.com:svn (ESTABLISHED)

(更新されているディレクトリでsvn:externalsプロパティがez_setup svn://svn.eby-sarna.com/svnroot/ez_setupに設定されているようです。Webサイトに基づいて、これはtelecommunity.comにリダイレクトしていると思います)

その他の関連する可能性のあるポイント:

  • Python環境は2.5です。Debianボックスでは2.7です。
  • 私はSVNに精通しておらず、ハングしている理由が基本的に同じものかどうかはわかりません。また、svn:externalsの意味するところが何であるかを完全に確信していません。これは私の時間の前に設定されました。
  • Pythonスクリプト自体は、Amazon S3から大量のデータ(場合によっては〜10MB)のデータのチャンクを取得しており、これは遅くなる傾向があります(ダウンロード時間はサーバー間(異なるデータセンターであっても)が通信するのにかかる時間と比較すると、3分は長いように見えます。同様に、一部のSVNリポジトリはかなり大きいため、基本的にこれらの一部は操作は長時間実行とにかくですが、場合によっては数時間または数日間ハングするようにも見えます。
  • あるサーバーで、今朝、OOMキラーがMySQLを取り出しました。詳細に調べたところ、メモリ使用率は90%、スワップ使用率は100%でした(Monitの報告によると)。ハングした大量のバックログを殺すPythonジョブは、これらの統計をそれぞれ60%と40%に減らしました。これにより、少なくとも(すべてではないにせよ)データの一部がダウンロード/読み取られているような印象を受けます(そして、プロセスがハングしている間、メモリに保持されます)。
  • これらのcronジョブは、S3からのリソースのリストを要求し、それに応じてMySQLテーブルのリストを更新しています。各ジョブは同じリストで開始されるため、同じリソースを要求し、同じテーブルを更新しようとします。
  • ハングしたプロセスの1つからのトラフィックをキャプチャすることができました。それは私には少し不可解ですが、それは接続がアクティブで機能していて、非常に非常に遅いことを示しているのでしょうか?混乱を避けるために、それを要旨として提供しました(これは約2時間のキャプチャに相当することに注意してください): https://Gist.github.com/petronius/286484766ad8de4fe20b これは赤いニシンだったと思います。そのポートにはアクティビティがありますが、それはS3への接続と同じ接続ではありません-それは他のランダムなサーバーアクティビティです。
  • 別のデータセンターのボックスでこの問題を再現しようとしました(a VM同じシステム設定で同じバージョンのDebianを実行しています))、運が悪かったです(私はおそらく問題は this one に関連していましたが、これらの問題が発生しているボックスはVMではなく、ifconfigによるドロップされたパケットはありません。これはネットワーク構成を示していると思います問題ですが、どこから始めればよいかわかりません。

だから私の質問は:

  • これをシステムレベルで修正できますか、それとも各プロセスで問題が発生していますか?
  • OS XとLinuxがreadの呼び出しを処理する方法について根本的に異なるものはありますか?
7

これをシステムレベルで修正できますか、それとも個々のプロセスで問題が発生していますか?

プロトコルレベルで何が起こっているのか不明であるため、言うのは困難です。基本的にread(2)は無期限にブロックします:-

  • TCP接続は開いたままです。
  • 少なくとも1バイトのデータが到着することを期待しています。
  • 送信者はデータを送信する準備ができていません。

さて、もう一方の端がデータを送信する前に最初にあなたからの応答を期待している、またはもう一方の端からの以前の応答がSVNが何かをすることを期待しているなど、プロセスに何か問題がある可能性がありますelse =追加のデータを要求する前。たとえば、クライアントにいくつかの情報を再送信させるエラー応答が返されたとします。

このデータの送信者が何を期待しているのかを判断する必要がある情報からは不可能であるため、これを適切に修正することはできません。ただし、問題を回避して報告する方法はいくつかあります。

  • 単純なブロッキングモードでwaitを使用するのではなく、waitを実行して、親プロセスでアラームを構成します。これで、プロセスが一定期間内に完了しなかった場合、プロセスを強制終了して、これが発生したことを報告できます。これを行う簡単な方法は、timeoutコマンドを呼び出すようにsubprocess.Popenを変更することです。
  • 読み取りタイムアウトソケットオプションを設定するように読み取りを変更します。これを行うには、コードを変更するか、インターポーザーを使用してデフォルトのsocketシステムコールをオーバーライドし、レシーバーにもタイムアウトを追加します。どちらも簡単ではありません。これにより、svnが予期しない動作をする可能性があります。

OS XとLinuxが読み取り呼び出しを処理する方法について根本的に異なるものはありますか?

私はこれに対する答えはわかりませんが、両方が正反対に正しく動作している場合、それらは両方とも同じように動作するはずです。データを送信する準備がまだ整っていないソケットから読み取ろうとすると、ストリームを無期限にブロックすることが予想される動作です。

全体的に見て、svnコマンドが特定の時間内に完了することを期待するのが最善の攻撃です。それが殺さない場合、あなたが殺したと報告します。

3
Matthew Ife

私は上記の問題を理解したと思いますが、ほとんどの謎はサーバーで何が起こっているのかについての私の誤解から生じています。

次の基本的な問題がありました:

  • タイムアウトが設定されているはずの(そして私が設定したと想定していた)Pythonスクリプトは設定されていませんでした。それらのいくつかは、S3への接続時に無期限にハングし、読み取りが完了するまで無期限に待機するという動作を示しました。コードをくまなく調べて、グローバルソケットタイムアウトが設定されていて、設定が解除されていないことを確認すると、その部分は解決したようです。
  • 古いPythonプロセスのいくつかはハングしているように見えましたが、詳細に検査すると(本当にブロックされたプロセスが除かれた後)、それらは単にそれらのキーのステータスをチェックするために大きなS3バケットをリストしていましたバケット、およびこの操作が完了するまでに数時間または数日かかっていました。
  • SVNチェックアウトコマンドは、非常に深いディレクトリ構造に多数のファイルがある非常に大規模なプロジェクトを更新するときに、長時間(まだ)ハングしていました。クライアントは読み取りが完了するのを待っていますが、これは完全に正当なことです(クライアントに送り返す必要があるデータを収集するためにリポジトリサーバーに長い時間がかかるようです)。

何が起こっているのかを説明するために、ここではこの回答は残しておきますが、実際に起こりうる問題が何であったかについて彼が正しかったので、マシューの質問を受け入れます。

1