簡體   English   中英

如何保持HttpClient連接保持活躍?

[英]How to keep HttpClient Connection Keep-Alive?

我正在使用HttpClient POST方法。 我需要創建一次HttpClient ,並且應該使用Keep Alive Connection。 但我想在我的情況下,它每次都建立一個新的連接。

因此,我需要為HttpClient使用Keep Alive連接。

這是我的代碼片段,任何幫助將不勝感激。

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

10:07:29.746:D / org.apache.http.headers(1529):>>連接:Keep-Alive

您正在請求keepalive。

10:07:29.836:D / org.apache.http.wire(1529):<< “連接:關閉[EOL]”

服務器拒絕它。

在你的最后,你無能為力。

從HTTP 1.1開始,默認情況下啟用keep-alive。 如果您不希望在處理HTTP 1.1時顯式重用連接,則需要關閉連接。

對於1.0,標題是您為此“連接:保持活動”設置的標題。這僅表示您要重用連接的服務器。 當處於壓力或其他原因時,服務器可能會選擇采取不同的行動,如下所述。

在大多數情況下,這里的大多數答案都是正確的,在這里添加keep alive標頭並且效果很好。 以下說明適用於您執行此操作但仍無效的情況。


服務器端問題

通常情況下,當服務器正常運行時,答案將集中在設置上,但這並非完全正確。 服務器(如Rudra )可以在不同情況下表現不同。 保持活動狀態伴隨着服務器在斷開連接之前為您提供的許多請求,這也是為了向其他人提供服務,因此在高負載的情況下,某些服務器可能會采取減少保持活動請求的數量為每個新連接服務。

從上次收到的請求中還有一個超時設置,如果在該時間窗口中沒有進一步的請求,最終會導致斷開連接。 很少有現代服務器可以根據他們目前的容量改變這一點,或者在恐慌情況下將其降低到0,使得保持活力毫無意義。 因此,如果您嘗試連接的服務器正在經歷任何此類(競賽,恐慌)情況,它可能會選擇放棄您的請求。


客戶端問題

出於文檔目的。 來自hc.apache.org

HttpClient始終盡力重用連接。 默認情況下啟用連接持久性,無需配置。 在某些情況下,這可能導致連接泄漏,從而導致資源損失。 禁用連接持久性的最簡單方法是提供或擴展連接管理器,該管理器在releaseConnection方法中釋放時強制關閉連接。

HttpClient提供了這些(讀取:瑣碎的)開箱即用的東西。 但是仍然存在Apache提供的其他東西,您可以添加它以提高其性能。

例如,可以為HttpClient定制ConnectionManager。

因此,可以阻止保持活動/連接持久性的事情是您可能正在使用的連接管理器(在您的情況下這不是真的,但在其他幾種情況下可能也是如此)。 如果您從某個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足夠公平。 如果您發現性能下降,可以編寫自己的連接管理器。

但是,在你的情況下,你的服務器不是非常支持它可能根本不尊重Keep-alive,即使你有那些標題而不是。 在向服務器發送新請求中發送keep-alive以確定服務器是否投訴時,您需要檢查響應中的超時標頭。

為什么不用你所有的請求只使用同一個客戶端?

我一直在研究一個需要向許多Web服務請求大量數據的應用程序,為此我只使用一個靜態客戶端並且工作完美!

我創建了一個返回HttpClient的類和另一個管理我所有請求的類(POST和GET),很簡單;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM