web-dev-qa-db-ja.com

HttpClient接続のキープアライブを維持する方法は?

私はHttpClient POSTメソッドを使用しています。HttpClientを一度作成する必要があり、Keep Alive Connectionを使用する必要があります。しかし、私の場合、新しい毎回接続。

だから、私はKeep Alive接続をHttpClientに使用する必要があります。

これが私のコードスニペットです。

ClientConnectionManager mgr = httpclient_recv.getConnectionManager();
    hp = httpclient_recv.getParams();
    httpclient_recv = new DefaultHttpClient(
    new ThreadSafeClientConnManager(hp,mgr.getSchemeRegistry()), hp);

    while (true) {

        try {

            Java.util.logging.Logger.getLogger("org.Apache.http.wire")
                    .setLevel(Java.util.logging.Level.FINER);
            Java.util.logging.Logger.getLogger("org.Apache.http.headers")
                    .setLevel(Java.util.logging.Level.FINER);

            System.setProperty("org.Apache.commons.logging.Log",
                    "org.Apache.commons.logging.impl.SimpleLog");
            System.setProperty(
                    "org.Apache.commons.logging.simplelog.showdatetime",
                    "true");
            System.setProperty(
                    "org.Apache.commons.logging.simplelog.log.httpclient.wire",
                    "debug");
            System.setProperty(
                    "org.Apache.commons.logging.simplelog.log.org.Apache.http",
                    "debug");
            System.setProperty(
                    "org.Apache.commons.logging.simplelog.log.org.Apache.http.headers",
                    "debug");

            ByteArrayEntity bae = new ByteArrayEntity(byteData);
            bae.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
                    "binary/octet-stream"));

            httppost_recv.setHeader(HTTP.CONN_DIRECTIVE,HTTP.CONN_KEEP_ALIVE);
            httppost_recv.setEntity(bae);



            {
                System.out.println("res b4 response");
                 response_recv = httpclient_recv
                        .execute(httppost_recv);
                 response_recv.getEntity().consumeContent();
                System.out.println("res a4 response");
                if (response_recv != null) {
                    byteArray = EntityUtils.toByteArray(response_recv
                            .getEntity());
                    playing  = true;
                }
                        }
                 }

また、logcatログは次のとおりです。

12-03 10:07:29.466: I/System.out(1529): res b4 response
12-03 10:07:29.646: D/org.Apache.http.wire(1529): >> "POST /ping HTTP/1.1[EOL]"
12-03 10:07:29.666: D/org.Apache.http.wire(1529): >> "Connection: Keep-Alive[EOL]"
12-03 10:07:29.686: D/org.Apache.http.wire(1529): >> "Content-Length: 1[EOL]"
12-03 10:07:29.705: D/org.Apache.http.wire(1529): >> "Content-Type: binary/octet-stream[EOL]"
12-03 10:07:29.716: D/org.Apache.http.wire(1529): >> "Host: 192.168.1.36[EOL]"
12-03 10:07:29.725: D/org.Apache.http.wire(1529): >> "User-Agent: Apache-HttpClient/UNAVAILABLE (Java 1.4)[EOL]"
12-03 10:07:29.736: D/org.Apache.http.wire(1529): >> "[EOL]"
12-03 10:07:29.746: D/org.Apache.http.headers(1529): >> POST /ping HTTP/1.1
12-03 10:07:29.746: D/org.Apache.http.headers(1529): >> Connection: Keep-Alive
12-03 10:07:29.756: D/org.Apache.http.headers(1529): >> Content-Length: 1
12-03 10:07:29.756: D/org.Apache.http.headers(1529): >> Content-Type: binary/octet-stream
12-03 10:07:29.765: D/org.Apache.http.headers(1529): >> Host: 192.168.1.36
12-03 10:07:29.765: D/org.Apache.http.headers(1529): >> User-Agent: Apache-HttpClient/UNAVAILABLE (Java 1.4)
12-03 10:07:29.776: D/org.Apache.http.wire(1529): >> "[0x0]"
12-03 10:07:29.796: D/org.Apache.http.wire(1529): << "HTTP/1.1 200 OK[EOL]"
12-03 10:07:29.805: D/org.Apache.http.wire(1529): << "Server: gSOAP/2.8[EOL]"
12-03 10:07:29.816: D/org.Apache.http.wire(1529): << "Content-Type: binary/octet-stream[EOL]"
12-03 10:07:29.826: D/org.Apache.http.wire(1529): << "Content-Length: 2048[EOL]"
12-03 10:07:29.836: D/org.Apache.http.wire(1529): << **"Connection: close[EOL]"**
12-03 10:07:29.887: D/org.Apache.http.headers(1529): << HTTP/1.1 200 OK
12-03 10:07:29.896: D/org.Apache.http.headers(1529): << Server: gSOAP/2.8
12-03 10:07:29.896: D/org.Apache.http.headers(1529): << Content-Type: binary/octet-stream
12-03 10:07:29.906: D/org.Apache.http.headers(1529): << Content-Length: 2048
12-03 10:07:29.906: D/org.Apache.http.headers(1529): << **Connection: close**
12-03 10:07:29.916: I/System.out(1529): res a4 response
11
G M Ramesh

10:07:29.746:D/org.Apache.http.headers(1529):>>接続:キープアライブ

キープアライブを要求しています。

10:07:29.836:D/org.Apache.http.wire(1529):<< "Connection:close [EOL]"

サーバーはそれを拒否しています。

あなたの側でそれについてあなたができることは何もありません。

9
user207421

HTTP 1.1以降、キープアライブはデフォルトで有効になっています。 HTTP 1.1を扱うときに明示的に再利用したくない場合は、接続を閉じる必要があります。

1.0の場合、ヘッダーはこの「接続:キープアライブ」に設定するものです。これにより、接続を再利用するサーバーのみが親密になります。ストレスがかかっている場合やその他の理由で、サーバーは以下で説明するように異なる動作をする場合があります。

ほとんどの目的で、ここでのほとんどの答えは正しいです。ここで、キープアライブヘッダーを追加すると、うまく機能します。次の説明は、それを行ったが、それでも機能しない場合のシナリオです。


サーバー側の問題

通常、回答はサーバーが正常に動作する場合の設定に集中しますが、これは完全には当てはまりません。サーバー( Rudra など)は、状況によって動作が異なるように構築されています。キープアライブには、接続を切断する前にサーバーが提供する多数のリクエストが付属しています。これは、他のユーザーにもサービスを提供できるようにするため、高負荷の場合、一部のサーバーはキープアライブリクエストの数を減らすことに頼る場合があります新しい接続ごとに提供されます。

また、最後に受信したリクエストからタイムアウトが設定されているため、その時間帯にリクエストがそれ以上行われないと、最終的に切断されます。最近のサーバーでは、現時点での容量に基づいてこれを変更したり、パニック状態で0に落としてキープアライブを無意味にしたりすることはほとんどありません。したがって、接続しようとしているサーバーがそのような(レース、パニック)状態のいずれかを通過している場合、要求を破棄することを選択する可能性があります。


クライアント側の問題

文書化の目的で。 hc.Apache.org から:

HttpClientは常に接続の再利用に最善を尽くします。接続の持続性はデフォルトで有効になっており、構成は必要ありません。状況によっては、接続がリークし、リソースが失われる可能性があります。接続の永続性を無効にする最も簡単な方法は、releaseConnectionメソッドでリリース時に接続を強制的に閉じる接続マネージャーを提供または拡張することです。

HttpClientは、これらの(read:trivial)ものをすぐに利用できます。しかし、それでも、Apacheによって提供される、パフォーマンスを向上させるために追加できるものが他にもあります。

たとえば、ConnectionManagerはHttpClient用にカスタマイズできます。

したがって、キープアライブ/接続の永続性をブロックできるのは、使用している可能性のある接続マネージャーです(これはあなたのケースでは当てはまりませんが、他のいくつかのケースでは当てはまる可能性があります)。いくつかのAPIから呼び出しを行うためのClientオブジェクトを取得している場合、これは完全に未知/抽象的な事実である可能性があります。これをカスタマイズする方法の例を以下に示します(Apache接続管理ドキュメントから)

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// Increase max total connection to 200
cm.setMaxTotal(200);
// Increase default max connection per route to 20
cm.setDefaultMaxPerRoute(20);
// Increase max connections for localhost:80 to 50
HttpHost localhost = new HttpHost("locahost", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50);

CloseableHttpClient httpClient = HttpClients.custom()
    .setConnectionManager(cm)
    .build();

(詳細は 接続管理に関するApacheのドキュメント を参照してください)

この問題が発生した場合は、CMなしで試すか、独自のHttpClientオブジェクトを作成してください。複数の接続にCMを使用する必要もありません。作り付けのCMは十分に公正です。パフォーマンスが低下した場合は、独自の接続マネージャーを作成できます。

しかし、あなたのケースでは、あなたのサーバーはあまりサポート的ではなく、たとえそれらのヘッダーがあってもなくても、キープアライブをまったく尊重しないかもしれません。サーバーがクレームであることを確認するために、サーバーに新しいリクエストでキープアライブを送信する際に、タイムアウトヘッダーを確認する必要があります。

4
Kumar Mani

すべてのリクエストに同じクライアントを使用しないのはなぜですか???

私は多くのWebサービスに大量のデータを要求する必要があるアプリに取り組んでおり、そのために静的クライアントを1つだけ使用して完璧に動作します!

私はHttpClientを返すクラスと、すべてのリクエスト(POSTおよびGET)を管理する別のクラスを作成しました。