Python Web サービスとクライアント Web サイトを並行して開発しています。クライアントからサービスに HTTP リクエストを送信すると、1 回の呼び出しで常に socket.py の socket.error が発生します。
(104、「ピアによる接続のリセット」)
Wireshark でリッスンすると、「良い」応答と「悪い」応答が非常によく似ています。
- OAuth ヘッダーのサイズが原因で、要求は 2 つのパケットに分割されます。サービスは ACK で両方に応答します
- サービスは、ヘッダーごとに 1 つのパケットで応答を送信します (HTTP/1.0 200 OK、次に Date ヘッダーなど)。クライアントはそれぞれに ACK で応答します。
- (良い要求) サーバーは FIN、ACK を送信します。クライアントは FIN、ACK で応答します。サーバーは ACK を返します。
- (不正な要求) サーバーが RST、ACK を送信し、クライアントが TCP 応答を送信しない場合、クライアント側で socket.error が発生します。
Web サービスとクライアントの両方が、glibc-2.6.1 を実行する Gentoo Linux x86-64 ボックスで実行されています。同じ virtual_env 内で Python 2.5.2 を使用しています。
クライアントは、httplib2 0.4.0 を呼び出してリクエストを行う Django 1.0.2 アプリです。OAuth トークンを常に空の文字列に設定して、OAuth 署名アルゴリズムでリクエストに署名しています。
このサービスは、Python の wsgiref.simple_server を使用する Werkzeug 0.3.1 を実行しています。問題なく wsgiref.validator を介して WSGI アプリを実行しました。
これは簡単にデバッグできるように思えますが、サービス側で適切なリクエストを追跡すると、socket._socketobject.close() 関数でデリゲート メソッドをダミー メソッドに変えて、不適切なリクエストのように見えます。send または sendto (どちらかは覚えていません) メソッドがオフになると、FIN または RST が送信され、クライアントは処理を開始します。
「ピアによる接続のリセット」はサービスに責任があるようですが、httplib2も信頼していません。クライアントに過失がある可能性はありますか?
** さらなるデバッグ - Linux 上のサーバーのように見えます **
私は MacBook を持っているので、1 台でサービスを実行し、もう 1 台でクライアント Web サイトを実行してみました。Linux クライアントは、バグ (FIN ACK) なしで OS X サーバーを呼び出します。OS X クライアントはバグ (RST ACK、および (54、「ピアによる接続のリセット」)) を使用して Linux サービスを呼び出します。つまり、Linuxで実行されているサービスのようです。x86_64ですか?悪いglibc?wsgiref? まだ見て...
** さらなるテスト - wsgiref は不安定に見える **
Apache と mod_wsgi を使用して本番環境に移行し、接続のリセットはなくなりました。以下の私の回答を参照してください。ただし、接続のリセットをログに記録して再試行することをお勧めします。これにより、サーバーは開発モードで問題なく動作し、本番環境でも安定して動作します.