记录一次高并发下性能问题解决

最近在重构底层推送服务,遇到了性能问题,在这里总结下经验
性能需求:支撑推送调用量持续4小时每小时1800万(tps5000),最好同步返回结果,每分钟响应时间TP99小于1s,平均小于100ms。
我们来分析下,首先这个量级确实有点大,如果同步返回, 又对响应时间要求比较高,那先做成同步的看看效果。

新的开始

分析接口逻辑简单对内存需求不大,关键点在于有需要使http调用推送多厂商的接口,也就是说调用多厂商的性能直接我们接口的性能,经过验证http调用推送厂商时间会随着请求量的增加而增大,平均时间最大400ms,这无法满足业务。
记录一次高并发下性能问题解决

新的改变

受限于第三方的请求时效,最快速的上线解决办法是改为异步,异步使用线程池或者是mq,线程池优势快速调整参数改变处理能力,缺点是重启或发布会丢失队列的消息,mq可以削峰,相对于本地的线程池队列不丢数据,把内存转到mq服务并解耦方便处理消息,但短时间内开发成本高些,无论是选哪个思想都是放到队列,慢慢的消费。
按照以上设计上线发现了新的问题,当高并发量持续几个小时,上游以每80ms,进入队列,但是我们的处理能力越来越慢,原因是调用http推送多厂商随着并发数增大而增加,平均已经400ms,也就是说进入队列的速度是消费队列速度的5倍,如果处理不当会造成线程池队列积压超过最大队列数走拒绝策略,默认报RejectedExecutionException丢失推送消息,如果使用mq队列会积压,要消耗更多的消费者机器,如果不增加机器导致消息延迟推送,无论哪种方式,最后我们用了38台4G4C机器才保证了这4个小时所有消息不丢失处理完,成本太大了。

二次改变

到现在真的是很郁闷,为了这个简单业务需求要投入这么大的成本,如果真的要30多台机器,无论是费用还是维护成本无法接受,想想问题的瓶颈点,因为http调用多厂商慢导致处理能力慢,攻克http请求时间问题是根本的解决方案,我们在上面监控截图可以看到,当调用量不大时请求到响应不到20ms,那为什么会调用量增加响应时间变长呢,
1.可能多厂商的api带宽不足
2.可能中间的网络环境造成
3.自己本身请求代码问题。
找厂商技术支持与我们运维看看前2个问题结果是没问题,平均响应时间很低的。
后来翻阅的书籍和技术博客,发现有一文章一下子提醒了我

https://www.jianshu.com/p/4d877d56eead

感谢这位作者帮我定位到了问题,在使用httpClient调用时直接使用了多厂商api接口文档的代码demo,每次指令下发,都会创建一个新的HttpClients,还有关闭开销都太大。实际httpclient是一个线程安全的类,全局保留一个即可,把httpClient初始化到静态全局变量里,每次都使用它。经过这个优化,5000tps系统也压力很小,5台机器可以支撑,同时不需要异步队列,可以同步返回结果。
记录一次高并发下性能问题解决

总结

在高并发时使用一个全局httpclient即可,最大连接数可以设定500,量少时发现不了问题,量大很多性能不好的代码细节都会暴露,所以多储备知识点是高级工程师的必备。
记录一次高并发下性能问题解决