获取负载测试的NoHttpResponseException

我正在为我的应用程序运行负载测试。 我有两台服务器:一台是我的应用程序,另一台是负责让我回复的虚拟服务器。

在我的虚拟服务器中,我有以下jsp代码:

    

我正在使用tomcat7运行应用程序。 我的server.xml连接池(在两个服务器中)看起来像:

   

我从服务器运行的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个并发线程请求有任何错误。

我找到了问题的根本原因。

由于某种原因,连接变得无效,并且池不知道它。

在这种情况下,抛出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; } }); 

此解决方案适用于HttpClient 4.5及更高版本。 不推荐使用DefaultHttpClient。

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

我在https://issues.apache.org/jira/browse/HTTPCLIENT-1610上记录的缺陷中发表了评论。 正如您所看到的,一旦我将非活动的http连接validation – 重用前validation时间从默认的2000毫秒减少到100毫秒,我再也看不到任何NoHttpResponseException了。我还没有测试过找出什么是阈值在我的环境中使用staled连接无效,但100毫秒肯定在我的环境中足够短。