type
Post
status
Published
date
Apr 25, 2024
slug
summary
Timeout waiting for connection from pool,版本httpclient-4.5.12.jar
tags
问题集(技术)
category
技术分享
icon
password
😀
今天对接一个需求需要处理大量数据且每条数据都需要调用第三方平台校验,所以使用apache的HttpClient进行调用(版本4.5.12),写完高并发测试发现经常抛出Timeout waiting for connection from pool,从而引发我的深思与深究
 

📝 通过问题深挖HttpClient为何会在高并发下抛出从连接池获取连接超时

正常测试并没有发现有该问题

使用测试数据30w+串行跑并没有发现有问题,后面因为测试机器是2核也就调整为4个线程跑也是顺利进行;后续升级为4核机器跑设置为9(IO线程可以设置为线程数的2倍+1)个线程进行测试发现出现问题了,但有时又是正常的,一开始也没太注意以为是调用别人服务连接超时了,少许也是可以容忍的就发预发进行压测,引发问题明显暴露

问题定位

根据关键信息google一下,已经有很多人遇到类型问题,引用了两个较为不错的博客,参考文章1,基本都提到点,参考文章2,则是拓展没有正常关闭连接引发的问题。通过前人经验查看了引用的工具类发现路由配置被注释了😂,看了一下源码Cpool实现实例化默认路由最大并发量为2(同一个域名同时可使用连接数),最大连接数20,好了定位到是路由并发数太小的问题。但为什么2核机器启用4个线程没暴露问题??

深究2核开启4个线程为什么没有暴露问题

带着这个问题,看了一下代码并测试了一下,复现了问题,写个简单例子,开启debug模式可以看到配置及实时信息,如下:开启10个线程,或链接池获取链接等待时间1s,请求使用sleep阻塞2s。测试结果:当请求不阻塞时也没报过错,原因是因为这个测试接口响应时间开始2个连接因为建立会比较慢700ms左右,后续的复用连接从调用到返回释放连接才70ms左右,一共10个线程2个一次分5组,700ms+4*70ms大约980ms,而从连接池获取连接会等待1s所以在阻塞最久的线程超时前连接已经释放能够获取到,所以并不会报错,也就是导致测试没问题。但这里测试了10个线程,预发是9个线程他为什么会出现问题,其实从实验能得出一个结论这个超时和接口响应时间也有关系,当接口响应时间慢了就会拖长整体,加上数据量上来了就会慢慢累加从而保留问题。

🤗 总结归纳

通过上述例子可以得出一下经验,
  1. 在引用别人工具类时如果能请教一下他封装的内容或者阅读一下别人的描述会起到一定的警惕效果(很明显当时没有这么做);
  1. 再者就是需要高并发测试时尽量模拟出线上会出现的数据量以及并发度,充分测试,让问题提前暴露,如果无法确定数据量和并发度自己需要考虑一下程序所能承受的极限进行限制

📎 参考文章

 
💡
有关问题,欢迎您在底部评论区留言,一起交流~
如何做好一件事乡镇地理位置数据获取(geoJSON)
Loading...