web-dev-qa-db-ja.com

ソケットConnectExceptionの原因は何ですか:接続がタイムアウトしましたか?

_Java.net.HttpsURLConnection_を使用してHTTPS経由でシリアル化されたオブジェクトを送信することにより、サーバーと通信するWebstartクライアントがあります。

ローカルマシンとオフィスにあるテストサーバーではすべてが完全に正常に機能しますが、実稼働サーバーとステージングサーバーでのみ(そして散発的に)発生する非常に奇妙な問題が発生しています。これらのサーバーと私たちのオフィスのサーバーの主な違いは、サーバーが別の場所にあり、クライアントサーバーとの通信がかなり遅いことですが、それ以前の本番環境でも長い間正常に機能していました。

とにかく、これが起こっていることです:

  • クライアントは、読み取りタイムアウトなどのオプションとHttpURLConnectionの_Content-Type_などのプロパティを設定した後、getOutputStream()を呼び出してストリームを書き込みます。
  • この時点で、私が知る限り、クライアントはしばらくの間ハングします。
  • 次に、クライアントは次の例外をスローします。
 Java.net.ConnectException:接続がタイムアウトしました:Java.net.PlainSocketImpl.socketConnect(ネイティブメソッド)
のconnect 
、Java.net.PlainSocketImpl.doConnect(不明なソース) 
 at Java.net.PlainSocketImpl.connectToAddress(Unknown Source)
 at Java.net.PlainSocketImpl.connect(Unknown Source)
 at Java.net.SocksSocketImpl.connect(Unknown Source )
 at Java.net.Socket.connect(Unknown Source)
 at com.Sun.net.ssl.internal.ssl.SSLSocketImpl.connect(Unknown Source)
 at com .Sun.net.ssl.internal.ssl.BaseSSLSocketImpl.connect(Unknown Source)
 at Sun.net.NetworkClient.doConnect(Unknown Source)
 at Sun.net.www.http.HttpClient .openServer(Unknown Source)
 at Sun.net.www.http.HttpClient.openServer(Unknown Source)
 at Sun.net.www.protocol.https.HttpsClient。(Unknown Source)
 Sun.net.www.protocol.https.HttpsClient.New(Unknown Source)
 atSun.net.www.protocol.https。 AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source)
 at Sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
 at Sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(不明なソース)
 at Sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
 at Sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)

これはSocketTimeoutExceptionではないことに注意してください。これは、HttpURLConnectionconnect()メソッドが、接続を確立する前にタイムアウトが経過するとスローすることを示しています。また、これが発生すると、conn.getResponseCode()を呼び出すことができ、応答コード200が返されます。

  • サーバー側では、EOFExceptionObjectInputStreamのコンストラクターにスローされます。コンストラクターは、シリアル化ヘッダーを読み取ろうとしますが、クライアントがOutputStreamに書き込むことができないため失敗します。

役立つ場合は、getOutputStream()を呼び出す前にHttpsURLConnectionで行われる呼び出しを次に示します(これを行うコードの構造全体ではなく、行われる呼び出しのみを表示するように編集されています) )::

_HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setReadTimeout(30000);
conn.setRequestProperty("Cookie", cookie);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-Java-serialized-object");
conn.getOutputStream();
_

問題は、これがどのように発生する可能性があるのか​​、特にそれが発生するのはたまに(私が知ることができる明確な活動パターンがない)であり、それでも(比較的)ある場合にのみ発生することを考えると、私にはわかりません。クライアントとサーバー間の待ち時間が長い。

_Java.net.ConnectException: Connect timed out_についてこれまでに見つけたものを考えると、サーバーが実行されているネットワーク上のネットワークまたはファイアウォールの問題ではないかと思いました...しかし、それはあまり意味がありませんリクエストが明らかにサーブレットに到達していることを考えると、私はそうしました。また、同じネットワークで実行されている他のアプリでも同様の問題は報告されていません。

誰かがこれの原因が何である可能性があるのか​​、あるいは私が何を調査する必要があるのか​​さえ知っていますか?

11
ColinD

私たちはあなたと同じようなケースでこれらに出くわしました。通常、高負荷であり、テストで再現するのは簡単ではありません。まだ修正していませんが、これが私たちが行った手順です。

ファイアウォールの問題の場合は、接続が拒否されるか、SocketTimeout例外が発生します。

1)サーバーのアクセスログでこれらのリクエストを追跡できますか?HTTPステータス200または404などが表示されていますか?この場合、サーバー(この場合はIIS)ログは、サーバーではなくクライアントが接続を閉じたことを示しています。だからそれは謎でした。

更新:クライアントが常に200を取得する場合、サーバーは実際に何らかの応答を送り返しましたが、応答のバイトサイズが疑われます(これが記録されている場合)アクセスログ)は、そのリクエストの通常の応答サイズの値とは異なる値を表示します。

同じサイズの応答が表示される場合は、サーバーが実際に正しく応答したが、接続のためにクライアントが応答を返さなかった(もっともらしいとは言えない)状態にあります。その間のどこかで終了しました。

2)ネットワーク管理チームはTCP/IPトラフィックを調べて、HTTP/TCP-IP会話を終了しているエンド(または中間ルーター)を特定しました。そして、どちらの端が接続を終了しているのかを理解したら、その理由を調べることです。十分な知識のある人が実行できます snoop

3)サーバー上で構成/制限されているリクエストの最大数はありますか?それは接続を抑制していますか?

4)リクエストをドロップできる中間ロードバランサーはありますか?

更新:もう1つやりたかったのですが、完了しませんでした。クライアントとサーバーの間に静的ルートを作成して、との間のホップ数を減らすことです。ネットワーク関連の接続が切断されていないことを確認してください。 http://en.wikipedia.org/wiki/Static_routing を参照してください

5)別の提案は、 ConnectTimeout も設定して、これらがより高い値で機能するかどうかを確認することです。 更新:試してみてください conn.getErrorStream()

接続が失敗したが、サーバーが有用なデータを送信した場合は、エラーストリームを返します。接続が接続されていない場合、接続中にサーバーでエラーが発生しなかった場合、またはサーバーでエラーが発生したがエラーデータが送信されなかった場合、このメソッドはnullを返します。

6)サーバー上で一連のスレッドダンプを5秒間隔で取得して、サーバー上でこれらの着信要求を示すスレッドがあるかどうかを確認することもできます。

更新:今日の時点で、この問題に対処することを学びました。これは、1日あたり40万件のリクエストのうち200〜300件の失敗率を合計したためです。 0.00075%

9
JoseK