web-dev-qa-db-ja.com

Tomcat、HTTP Keep-Alive、およびJavaのHttpsUrlConnection

SSLハンドシェイクを削減するために永続的な接続を維持する必要がある2つのTomcatサーバーがあります。一方のサーバー(プロキシ)はDMZにあり、もう一方のサーバーは安全に別のファイアウォールの背後にあります。プロキシは基本的に、リクエストを安全なマシンに転送する前にサニティチェックを行う単純なサーブレットを実行します。 。最初の要求で、マシンは実際の作業を実行する前に証明書を交換します。したがって、数分のタイムアウトで永続的な接続を維持したいと思います。

安全なサーバーと通信するために、プロキシ上のサーブレットはHttpsUrlConnectionを使用します。私はWireSharkをセットアップしましたが、セキュアマシンのコネクタにどのようなkeepAliveTimeout値を設定しても、TCP接続は約5または10後に閉じます。この数値は、デフォルトのタイムアウトと、JavaがHTTPキープアライブを処理する方法)と一致しているようです。この リンク は、JavaはKeep-Aliveサーバーから送信された場合はタイムアウト。それ以外の場合は、接続を閉じる前に5秒(直接接続)または10秒(プロキシ接続)を使用します。

私が理解しようとしているのは、TomcatにKeep-Aliveヘッダーを送信させる方法です。いいえ、Connection: Keep-Alive、 だが Keep-Alive: timeout=x

Apache HTTPサーバーを試してみましたが、httpd.confのkeepAliveTimeoutを変更すると、Keep-Aliveヘッダーのタイムアウト値が変更されます。さらにJavaはこのタイムアウトを尊重します。

UPDATE(12/23/11):さらにいくつかの実験を実行した後、ApacheのHttpClient(3.1)ではなく、迅速でダーティなコードを作成してみましたHttpsUrlConnection。 HttpClientがKeep-Aliveを使用するように設定されている場合、サーバーが接続を閉じるのを単に待機しているようです。どれくらい待つかはわかりませんが。 HTTP接続を3〜5分間維持するために撮影しています。

17
James Sheppard

TomcatコネクタのkeepAliveTimeoutを300000に設定することで、HttpClient 3.1を使用してHTTP接続を5分間開いたままにすることができました。WireSharkを使用して、サーバーが接続を終了し、HttpClientが単に待機することを確認しました。 HttpClientを介した後続のリクエストは、既存のTCP接続を再利用します(SSLハンドシェイクを回避します)。ただし、重要なのは、単一のHttpClientインスタンスを持つことです(つまり、毎回作成しないことです)。ほとんどの場合、私はHTTPClientのAPIメカニズムがどうなるかわかりませんでした。つまり、1つのHttpClientインスタンスを作成し、各リクエスト(POST、GETなど)に対して新しいPostMethod、GetMethodなどを作成します。これにより= TCP再利用される接続。

8
James Sheppard

Tomcatでは、次のようにHttpServletResponse.addHeader()を使用してHttpServeletにヘッダーを設定できました。

  response.addHeader("Connection", "Keep-Alive");
  response.addHeader("Keep-Alive", "timeout=60000");

これがクライアント側のHttpUrlConnectionで機能することをWireSharkで確認しました。 「Connection」ヘッダーを設定しないと機能しないため、両方を設定する必要があります。

5
Jan

Java API Http(s)UrlConnectionKeep-Alive情報を提供し、サーバーごとの接続プールを管理します 詳細な説明に従う (注意深く読んでください-各詳細が重要です)。

その場合、コードはバッファを完全に読み取り、ストリームを閉じ、IOExceptionの場合はエラーを読み取る必要があります。

もちろん、HttpClientの制約は少なくなりますが、状況を処理する最善の方法は、 以下のガイドライン のおかげで MultiThreadedHttpConnectionManager を使用することです。

2
Yves Martin