【问题标题】:Multiple post with Httpclient 4.0.3 hanging randomlyHttpclient 4.0.3 的多个帖子随机挂起
【发布时间】:2017-02-01 19:37:20
【问题描述】:

让我解释一下情况。

我有一个 servlet 将传出的 GET/POST 重定向到另一个域(某种代理)上的另一个项目,该项目的工作是处理它并返回一些东西(参数和 gif)。我使用 HttpClient 4.0.3 来执行此操作。

我的应用在启动时发送了多个 GET/POST,因此我设置了一次 ThreadSafeClientConnManager 以这种方式处理多个线程。

cm_params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(cm_params, 200);

ConnPerRouteBean connPerRoute = new ConnPerRouteBean();
HttpHost localhost = new HttpHost("localhost");
connPerRoute.setMaxForRoute(new HttpRoute(localhost), 50);

ConnManagerParams.setMaxConnectionsPerRoute(cm_params, connPerRoute);

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

cm = new ThreadSafeClientConnManager(cm_params, schemeRegistry);

然后我用这些参数创建一个新的 HttpClient,它应该足以同时处理一堆请求。当然,我在 public void service() 上为每个 GET/POST 执行此操作,但在创建它之后我使用相同的 Httpclient 对象。

httpclient = new DefaultHttpClient(cm, cm_params);

之后,我构建了我的 POST 并通过执行发送它,所有必需的参数和此类三重验证。

    HttpPost httpPost = new HttpPost(target+tmpString); 

    httpPost.setHeader("Host", request.getHeader("host"));
    httpPost.setHeader("User-Agent", request.getHeader("user-agent"));
    httpPost.setHeader("Accept-Encoding", request.getHeader("accept-encoding"));
    httpPost.setHeader("Accept", request.getHeader("accept"));
    ..etc..

    UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(params);
    urlEncodedFormEntity.setContentEncoding(HTTP.UTF_8);
    httpPost.setEntity(urlEncodedFormEntity);

    HttpResponse response = httpclient.execute(httpPost);

最后我读取了流并处理了实体...

    OutputStream os = res.getOutputStream();
    InputStream is = response.getEntity().getContent();
    byte[] buf = new byte[1024];
    for(int n;(n=is.read(buf))!=-1;)
    {
        os.write(buf, 0, n);
    }
    // Make sure to close
    is.close();
    os.close();

    // Flush entities just in case
    EntityUtils.consume(urlEncodedFormEntity);
    EntityUtils.consume(response.getEntity());
    urlEncodedFormEntity.getContent().close();
    response.getEntity().getContent().close();

所以我的问题是,当我加载我的页面时,代码运行良好。正确处理了 4 个发送的请求(1 个 GET,3 个 POST)。基本上返回我在页面上打印的一些参数和 1 个小 gif。

但是一旦我开始对我的应用程序进行压力测试,即 I.E.在 4-5 个选项卡中加载同一页面,每当我同时执行多个 POST 时,我的应用程序似乎随机挂起。我认为即使我使用 same Httpclient 对象 也不会有任何问题,因为我正确地声明了我的 ThreadSafeClientConnManager(我认为?)所以它应该处理多个线程。

有人知道我做错了什么吗?如果我一一加载我的标签,它不会挂起。就在我同时刷新多个标签时。

有人知道吗? :S (抱歉英语不是我的母语^^;)

【问题讨论】:

    标签: java httpclient


    【解决方案1】:

    @Apache Fan,设置这个:

    ConnManagerParams.setMaxTotalConnections(cm_params, 200); connPerRoute.setDefaultMaxPerRoute(50);

    怀疑我可能会失去连接,我打开 3-4 个选项卡并用完...每个选项卡可能有 4 个 POST,所以不会加起来:S

    【讨论】:

    • 这很好地解决了我遇到的一组非常相似的症状的问题。
    【解决方案2】:

    您可能想从HttpClient API 看看这个 -

    ThreadSafeClientConnManager 维护每个路由的最大连接限制以及总计。默认情况下,此实现将为每个给定路由创建不超过 2 个并发连接,并且总共不超过 20 个连接。对于许多现实世界的应用程序来说,这些限制可能过于局限,尤其是当他们使用 HTTP 作为其服务的传输协议时。但是,可以使用 HTTP 参数调整连接限制。

    也许您的应用程序的池连接已用完,您需要增加池的大小。

    【讨论】:

      【解决方案3】:

      最近我试图实现这一点,但我遇到了一些新问题,比如当我第一次发送请求时,它发送时没有 cookie,但第二次 httpContext 自动添加 cookie 但这是标准的发送方式,但有时您请求的服务器在没有 cookie 的情况下接受,因此我使用了 INTERCEPTOR。在第二次删除自动添加的 cookie 之后它工作正常请使用此 httpClient 拦截器使用以下代码:

      httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
      
              @Override
              public void process(HttpRequest request, HttpContext context)
                      throws HttpException, IOException {
                  LOG.info("***************** Entered My Interceptor ****************************");
                  Header[] headers = request.getAllHeaders();
                  for (Header eachHeader : headers) {
                      LOG.info("Headers -- Name: {}, Value: {} ",
                              eachHeader.getName(), eachHeader.getValue());
                  }
                  request.removeHeaders("Cookie");
              }
          }); 
      

      【讨论】:

        【解决方案4】:

        我陷入了同样的错误。我们注意到的是 HttpClient 不会自行关闭。

        我所做的是,我在未清除的 HttpClient 和 HttpResponse 上尝试了 HttpClientUtils.closeQuietly() 方法。它帮助了我的事业,它不再挂起。您也可以尝试一下。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多