HttpClient未设置connectTimeout导致线程池耗尽

一、背景

某商家反馈昨天晚上下单失败,研发查询网关日志后发现是edi集群的线程池耗尽,导致商家失败。

1
2
3
4
5
6
7
8
// 异常信息
{
"error_response":{
"en_desc":"platform connecting service process unknown exception:java.util.concurrent.RejectedExecutionException: [JSF-23003]Biz thread pool of provider has bean exhausted",
"zh_desc":"平台连接后端服务处理过程中出现未知异常:java.util.concurrent.RejectedExecutionException: [JSF-23003]Biz thread pool of provider has bean exhausted",
"code":67
}
}

二、可能原因分析

  1. 业务代码没有问题,但是瞬时流量加大,达到资源瓶颈;
  2. 业务代码有问题,使线程阻塞,长期占用线程,无法归还线程池;

三、定位过程

  1. 查询网关,定位线程池耗尽的服务器IP;
  2. 查询该IP上该时间段的流量,发现流量为0;

以上确定是由于业务代码有问题导致的;此时可通过如下两种方式继续定位问题:

  1. 精确定位: 在该机器上执行jstack pid,查看线程堆栈里jsf线程阻塞到哪行代码了;
  2. 范围定位: 在该机器上找到当时的日志,查看该线程最后执行的业务逻辑;

由于中间重启过集群,故采取第二种方法定位问题。

日志最终定位到是http请求节点阻塞,然后查看http节点的属性发现没有设置connectTimeout。我们使用的是httpclient-4.5.6,如果不设置connectTimeout则默认无限等待;

四、结论

  1. 使用第三方插件时,最好调研下常用配置,并全部配置上去。
  2. 避免出现默认值不符合预期时导致程序不健壮。

评论