2012-05-13 44 views
14

我正在爲我的應用程序運行負載測試。我有兩臺服務器:一臺使用我的應用程序和一臺虛擬服務器,負責讓我回應。獲取NoHttpResponseException負載測試

在我的虛擬服務器,我有以下JSP代碼:

<%@ page import="java.util.Random" %> 
<%@ page language="java" %> 
<%@ page session="false" %> 
<% 
    String retVal = "some json string"; 
    Thread.sleep(50); 
%> 

我正在與tomcat7應用。我的server.xml連接池(在兩個服務器)看起來像:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="1500" minSpareThreads="1000" prestartminSpareThreads="true" /> 
<Connector port="9031" protocol="HTTP/1.1" 
      connectionTimeout="20000" 
      maxConnections="4000" 
      executor="tomcatThreadPool" 
      redirectPort="8443" /> 

我是從服務器上運行的Java代碼:

HttpPost post = new HttpPost(bidderUrl); 
post.setHeader("Content-Type", "application/json");  
// I'm using http client with ThreadSafeClientConnManager 
// total conn = 500, max conn per route = 100, timeout=500millis 
HttpClient httpClient = httpClientFactory.getHttpClient(); 
    try { 
     post.setEntity(new StringEntity(jsobBidRequest)); 
     HttpResponse response = httpClient.execute(post); 
     ... 
    catch (NoHttpResponseException e){ 
     log.error(e); 
    } 

我正在與50個併發線程Jmetter(沒有環),並得到了很多例外的是這樣的:

org.apache.http.NoHttpResponseException The target server failed to respond 

當我運行僅5或10個併發線程的一切工作正常。

請問我可以在我的設置中出現什麼問題?據我的理解,我沒有看到50個併發線程請求的任何錯誤。

回答

30

我發現問題的根本原因。

由於某些原因,連接變得無效並且池不知道它。

在這種情況下,拋出了NoHttpResponseException,並且請求簡單地失敗。我認爲應該在HTTP客戶端池層解決這些問題,並且對我的代碼透明,但這不是它的行爲。

爲了解決這個問題,在HTTP客戶端的HttpRequestRetryHandler應覆蓋:

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry); 
... 
DefaultHttpClient httpClient = new DefaultHttpClient(cm, params); 
httpClient.setHttpRequestRetryHandler(new HttpRequestRetryHandler() { 
    @Override 
    public boolean retryRequest(IOException exception, int executionCount, 
           HttpContext context) { 
     if (executionCount > 3) { 
      LOGGER.warn("Maximum tries reached for client http pool "); 
       return false; 
     } 
     if (exception instanceof org.apache.http.NoHttpResponseException) { 
      LOGGER.warn("No response from server on " + executionCount + " call"); 
      return true; 
     } 
     return false; 
     } 
    }); 
+1

Julias,這非常有幫助!非常感謝您發佈您的解決方案。這正是我所期待的。 – trillions

+0

您的解決方案也幫助了我。在我的情況下,NoHttpResponseException僅在偶爾激活反病毒時發生。發送http請求時,防病毒軟件始終會進行一些掃描,偶爾會花費更長時間,導致請求失敗。 – Seigo

+0

@Seigo - 我知道這是一箇舊的線程,但是你有執行超時,因爲請求失敗?什麼設置導致請求失敗? –

1

我張貼登錄在https://issues.apache.org/jira/browse/HTTPCLIENT-1610缺陷的註釋。正如你所看到的,一旦我將靜態http連接的validate-before-reuse時間從默認的2000毫秒減少到100毫秒之類,我就再也看不到任何NoHttpResponseException了。我還沒有測試過要查明什麼是閾值在我的環境中使用staled連接無效,但在我的環境中,100毫秒肯定足夠短。

4

此解決方案適用於HttpClient 4.5及更高版本。 DefaultHttpClient已棄用。

HttpClientBuilder clientBuilder = HttpClients.custom(); 
clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, false));