簡體   English   中英

HttpClient無法從服務器獲取響應

[英]HttpClient can't get response from server

這個問題已經使我們的整個團隊半天無法工作了!

我們使用apache httpclient 4.3.x來發布並從提供http api的存儲服務器中獲取數據。 為了提高性能,我們使用了PoolingHttpClientConnectionManager

public HttpClient createHttpClient() {
    Registry registry = RegistryBuilder.create()....build();
    PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    connectionManager.setMaxTotal(50);
    connectionManager.setDefaultMaxPerRoute(50);

    CloseableHttpClient httpClient = HttpClients.custom()
       .setConnectionManager(connectionManager)
       .build();
    return httpClient;
}

然后,在程序中保存一個httpClient實例,將其與每個http請求一起重用:

全局httpClient:

HttpClient httpClient = createHttpClient();

發布一些數據:

HttpPost httpPut = new HttpPost("...");
HttpResponse response = httpClient.execute(httpPut);

// Notice we get the response content here!
String content = EntityUtils.toString(response.getEntity());
System.out.println(content);

httpPut.releaseConnection();
response.close();

然后得到:

HttpGet httpGet = new HttpGet("...");

// Blocked at this line !!!!
HttpResponse response = httpClient.execute(httpGet);

String content = EntityUtils.toString(response.getEntity());
System.out.println(content);

httpPut.releaseConnection();
response.close();    

請注意以下行: // Blocked at this line !!!!

程序已在該行被阻止,並且從不進入下一行。 在調試模式下,我可以看到它已在以下位置被阻止:

SocketInputStream.socketRead0()

我搜索了很多問題和文檔,但並不幸運。


我的NoConnectionReuseStrategy.INSTANCE只是通過設置NoConnectionReuseStrategy.INSTANCE解決它:

 HttpClients.custom()
       .setConnectionManager(connectionManager)
       // Following line fixed the problem, but why?
       .setConnectionReuseStrategy(NoConnectionReuseStrategy.INSTANCE)
       .build();

現在它沒有被阻止,但是為什么呢?

“重用連接”是什么意思? 使用NoConnectionReuseStrategy是否存在性能問題?

謝謝大家〜

我試圖重現阻止的http-get(也是我自己的一種練習),但是即使沒有關閉響應,我也無法阻止它。 我設法制作http-get塊的唯一時間是通過執行response.getEntity().getContent()而不讀取返回的InputStream且不關閉返回的InputStream 在我的測試中,我將Tomcat 7.0.47與兩個非常簡單的servlet(作為響應get響應“ OK”,另一個響應POST)用作服務器。 客戶端啟動了50個線程,每個線程執行30個交替的http-get和http-post請求(總共1500個請求)。 客戶端未使用RegistryBuilder ,而是使用默認值(由PoolingHttpClientConnectionManager本身創建)。

關於NoConnectionReuseStrategy :默認情況下(使用HttpClients.createDefault()創建的HttpClients.createDefault() ,我使用的是org.apache.httpcomponents:httpclient:4.3.1 ),連接池最多使用1個服務器的2個連接。 例如,即使5個線程同時對1個服務器執行各種請求,連接池也僅打開2個連接,將它們重新用於所有請求,並確保在任何給定時間1個線程使用1個連接。 這會對客戶端性能產生非常積極的影響,並顯着減少服務器上的負載。 您唯一必須確保的是在finally塊中調用response.close() (這可確保將連接返回到連接池)。 通過使用NoConnectionReuseStrategy您基本上可以禁用連接池:對於每個請求,將創建一個新的連接。 我建議您為org.apache.http.impl.conn.PoolingHttpClientConnectionManager類別啟用調試日志記錄,這非常有用。

關於httpPut.releaseConnection()注釋:實際上並不會釋放連接,它只是確保您可以在下一個請求中重用“ httpPut”對象(請參閱apidocs單擊顯示的鏈接)。 另請注意,在“ httpGet”的代碼中,您在“ httpPut”而不是“ httpGet”上調用releaseConnection()

不久前就遇到了這個問題。 如果其他人遇到此問題,這篇文章可能會有用。

我正在使用Java Servlet來處理我的請求。 當我使用PrintWriter實例寫入響應流時,客戶端被阻止。 嘗試直接寫入到OutputStream的response.getOutputStream.write("myresponse")並成功。

暫無
暫無

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

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