java httpClient 在默认配置下线程池堆满导致的一次大坑

阅读更多

最近系统在调用第三方系统时,出现一次严重的报错。导致系统半小时内出错率 timeout 奇高。

 

## 背景

项目使用 ClonableHttpClient 调用第三方 httpClient v4.5.3,使用时只调用了 connectTimeout, SocketTimeout. 第三方系统因故障导致服务器响应慢,期间出现较多的 ReadTimeout, 持续8分钟,随后恢复,而我们的系统当时正好处于业务高峰期,前端出现大量的 ReadTimeout, 持续了近40分钟。客户要求查原因

 

##  分析过程

- 系统上线运行了两年了,没有出现大的问题,这种场景的之前也遇到过,重启了事。

- 此次要求查 ROOT CAUSE。主要还是怀疑 httpClient 设置上。系统使用的代码如下

```

    CloseableHttpClient httpClient = context.getBean(CloseableHttpClient.class);
RequestConfig.Builder builder = RequestConfig.custom();
    builder.setAuthenticationEnabled(true);
    builder.setConnectTimeout(timeout);
    builder.setSocketTimeout(timeout);
    StringEntity stringEntity = new StringEntity(params, Charset.forName("UTF-8"));
HttpPost post = new HttpPost(address);
    post.setConfig(builder.build());
    post.setHeader("Content-type", "application/json; charset=utf-8");
    post.setEntity(stringEntity);
    HttpEntity httpEntity = httpClient.execute(post).getEntity();

```

 

基本是缺省配置,想来想去,最后认为应该是在第三方系统故障期间,堆积了大量的请求,进行了排队,即使第三方系统恢复了,入队的请求还要一个个的去消费。

参考 https://gaozzsoft.iteye.com/blog/2352241 

httpClient 默认会有一个线程池,默认的并发线程池为5,另中有一配置 setConnectionRequestTimeout 在无配置的情况下,排队的请求 会无限等待。 setConnectionRequestTimeout 可以设置一个等待可用线程池的最大等待时间。我们自行用代码验证这一逻辑,没有看到官方的描述。

 

设置之后,如果超时,会返回一个错误

```

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool

```

 

你可能感兴趣的:(httpClient,Timeout)