事件背景
我最近运维了一个网上的实时接口服务,最近经常出现Address already in use (Bind failed)的问题。
明显是一个端口绑定冲突的问题,于是大概排查了一下当前系统的网络连接情况和端口使用情况,发现是有大量time_wait的连接一直占用着端口没释放,导致端口被占满(最高的时候6w+个),因此HttpClient建立连接的时候会出现申请端口冲突的情况。
具体情况如下:
于是为了解决time_wait的问题,网上搜索了些许资料加上自己的思考,于是认为可以通过连接池来保存tcp连接,减少HttpClient在并发情况下随机打开的端口数量,复用原来有效的连接。
但是新的问题也由连接池的设置引入了。
问题过程
在估算连接池最大连接数的时候,参考了业务高峰期时的请求量为 1 分钟 1.2w pv,接口平响为 1.3s(复杂的广告推广效果模拟系统,在这种场景平响高是业务所需的原因),因此 qps 为 12000*1.3\60=260。
然后通过观察了业务日志,每次连接建立耗时 1.1s 左右,再留 70%+ 的上浮空间(怕连接数设置小出系统故障),最大连接数估计为 260 1.1 1.7 约等于 500。
为了减少对之前业务代码最小的改动,保证优化的快速上线验证,仍然使用的是HttpClient3.1 的 MultiThreadedHttpConnectionManager,然后在线下手写了多线程的测试用