获取负载测试的NoHttpResponseException

Jul*_*ias 18 java tomcat httpclient

我正在为我的应用程序运行负载测试.我有两个服务器:一个用我的应用程序和一个虚拟服务器负责让我回复.

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

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

我正在使用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" />
Run Code Online (Sandbox Code Playgroud)

我从服务器运行的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);
    }
Run Code Online (Sandbox Code Playgroud)

我正在使用50个并发线程(没有循环)运行Jmetter并得到很多例外:

org.apache.http.NoHttpResponseException The target server failed to respond 
Run Code Online (Sandbox Code Playgroud)

虽然我只运行5或10个并发线程,但一切正常.

你能告诉我在我的设置中可能出现什么问题吗?据我所知,我没有看到50个并发线程请求有任何错误.

Jul*_*ias 40

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

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

在这种情况下,NoHttpResponseException抛出并且请求完全失败.我认为这些问题应该在HTTP客户端池层中解决,并且对我的代码是透明的,但这不是它的行为.

要解决此问题,HttpRequestRetryHandler应覆盖HTTP客户端:

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;
      }
   }); 
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案对我有用,但是你应该使用新的StandardHttpRequestRetryHandler(3,true)代替你自己的重试处理程序实现.StandardHttpRequestRetryHandler仅重试那些http方法是幂等的调用 (6认同)

k_o*_*_o_ 6

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

HttpClientBuilder clientBuilder = HttpClients.custom();
clientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, false));
Run Code Online (Sandbox Code Playgroud)

  • 它只对 get、head 等幂等请求有用。发帖、删除都不行。 (2认同)

小智 5

我在https://issues.apache.org/jira/browse/HTTPCLIENT-1610记录的缺陷中发表了评论。正如您所看到的,一旦我将非活动http连接验证前重用时间从默认的2000毫秒减少到大约100毫秒,我就不会再看到任何NoHttpResponseException。我还没有测试过找出阈值是多少在我的环境中避免使用陈旧的连接,但 100 毫秒在我的环境中绝对足够短。