2012-05-13 30 views
14

私のアプリケーションの負荷テストを実行しています。私は2つのサーバーを持っています:1つはアプリケーションとダミーサーバーで、私の応答を得る責任があります。ロードテストのNoHttpResponseExceptionを取得します

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

私はtomcat7を使用してアプリケーションを実行している:私のダミーサーバーで

は、私は次のJSPコードを持っています。 (両方のサーバーで)私の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

ジュリアス、これは非常に役に立ちます!ソリューションを投稿していただきありがとうございます。それはまさに私が探しているものです。 – trillions

+0

あなたのソリューションはまた私を助けました。私の場合、NoHttpResponseExceptionは、ウイルス対策を有効にしたときにのみ発生することがありました。ウィルス対策ソフトウェアは、http要求が送信されたときにスキャンを実行し、時には少し時間がかかり、要求が失敗することがあります。 – Seigo

+0

@ Seigo - これは古いスレッドだと分かっていますが、リクエストが失敗したためにexecutionTimeoutがありましたか?要求が失敗する原因は何ですか? –

1

私はhttps://issues.apache.org/jira/browse/HTTPCLIENT-1610でログインして欠陥にコメントを投稿しました。ご覧のように、デフォルトの2000ミリ秒から100ミリ秒のような非アクティブなHTTP接続の検証前の再検証時間を短縮すると、NoHttpResponseExceptionはそれ以上表示されません。しきい値の値を調べるためのテストは行っていません私の環境では無効な接続を使用して無効にするが、100ミリ秒は間違いなく私の環境では十分に短い。

4

このソリューションは、HttpClient 4.5以降のバージョン用です。 DefaultHttpClientは推奨されていません。

HttpClientBuilder clientBuilder = HttpClients.custom(); 
clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, false)); 
関連する問題