15

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

私のローカルマシンとオフィスにあるテストサーバーではすべてが完全に正常に動作しますが、非常に奇妙な問題が発生しています。私が知っているこれらのサーバーと私たちのオフィスのサーバーの主な違いは、それらが別の場所にあり、クライアントとサーバー間の通信がかなり遅いということですが、これ以前の本番環境でも長い間問題なく動作していました.

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

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

これは ではないことに注意してください。これは、接続が確立される前にタイムアウトが発生した場合にonSocketTimeoutExceptionconnect()メソッドがスローすると言われています。HttpURLConnectionまた、これが発生すると、電話をかけることができconn.getResponseCode()、応答コード 200 が返されます。

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

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

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、サーバーが実行されているネットワーク上のネットワークまたはファイアウォールの問題ではないかと思いました...しかし、リクエストが明らかにサーブレットに到達しています。また、同じネットワーク上で実行されている他のアプリでは、同様の問題は報告されていません。

これの原因が何であるか、または私が何を調査すべきかさえ誰かが考えていますか?

4

2 に答える 2

13

あなたと同様のケースでこれらに遭遇しました。通常は負荷が高く、テストで再現するのは容易ではありません。まだ修正していませんが、これが私たちが行った手順です。

ファイアウォールの問題である場合は、接続拒否または 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 日あたり 400,000 件のリクエストのうち 200 ~ 300 件、つまり 0.00075 % になるからです。

于 2010-10-07T07:57:23.480 に答える