线程池优化实践

省流:通过线程池优化查询的业务逻辑,提高接口的效率,但需注意线程池的参数配置(阻塞队列大小,拒绝策略),避免带来其他的问题

问题背景:我们在使用系统的过程中,会遇到一些导出数据的场景,比如导出某个人最近一天的所有会议记录,以及会议的参会人信息

查询会议记录的业务逻辑

第一步 先根据用户查询查询用户的会议列

第二步 根据第一步查询出来的会议列表的会议信息,去循环查询每个会议的与会人信息

第三步 组合结果返回

业务代码(注:代码为模拟代码,并不涉及真实生产的代码)

并发为5时,请求耗时为平均在2000ms左右

并发50时,请求耗时为平均3000+ms左右

并发500时,请求耗时为平均4000+ms左右

随着并发量的上涨,查询数据的耗时越来越长,且并发为5时就已经达到2000ms左右了,耗时巨长

通过观察业务逻辑,循环查询每个会议的与会人信息的时候,并没有逻辑上的关联,也就是说,查询每个会议的与会人信息可以看作一个独立的过程,我们可以考虑用单独的线程去执行这个查询,通过并发来提高整体的效率。 改进后的流程为 第一步 先根据用户查询查询用户的会议列表 第二步 根据第一步查询出来的会议列表的会议信息,把每个会议的与会人查询提交到线程池当中去执行 第三步 组合结果返回

业务代码(注:代码为模拟代码,并不涉及真实生产的代码)
线程池参数

核心线程数为4(一般IO类型任务核心线程设为cpu * 2,计算类型任务时,核心线程设为cpu + 1,查询数据库或者访问第三方接口都数据IO类型的任务)

最大线程数设置为20

空闲线程存活时间 5分钟

任务队列大小 500

拒绝策略 直接拒绝

改进后 并发为5时,耗时为100+ms,速度得到质的提升

并发为50时,初期耗时为100ms,但是随着并发量的上升,后续的耗时逐渐开始变大 ,最大的时候为1000+ms,此时还出现阻塞队列中的任务,获取超时的问题,此时已经开始影响到了正常的业务,有部分的用户开始导出缺失的数据了

耗时增大 超时问题

并发为500时,也是同样的初期耗时较低,后续耗时变大,此时阻塞队列出现了大量超时的问题,大量用户已经开始导出空白的数据了,问题更加严重了

目前线程池出现的问题

问题一:后续耗时会变大?

问题二:阻塞队列已满,且出现大量队列中的任务超时问题,直接导致用户导出了空白的数据?

解决方案:
问题一 :耗时开始增大是正常的现象,因为当流量变大的时候,服务处理能力到最高后无法提升了,必然会有开始变慢的问题,影响不大,可通过限流或者是提醒用户稍等重试的方式较低影响
问题二 : 这个问题的本质是因为线程池参数设置得不合理

1、队列设置错误,该场景下,需要充分利用线程资源,将线程放入队列只会徒增等待的时间,导致等待队列里的任务全部超时抛出异常

2、拒绝策略设置错误,直接拒绝任务会抛出异常导致主流程中断,但此时主流程可能已经提交了部分任务,导致无效任务的提交

优化后参数

相比于之前,只修改了两个参数

1.把原来的任务队列设置为SynchronousQueue ,SynchronousQueue 是一个特殊的队列,其最大容量是1。也就是说,任何一次插入操作都必须等待一个相应的删除操作,反之亦然。如果没有相应的操作正在进行,则该线程将被阻塞,也就是说当线程池达到最大线程后,就不在接受新的任务了,解决阻塞队列内的任务超时的问题

2.拒绝策略改为CallerRunsPolicy,当阻塞队列满了,由提交任务的线程去完成执行,原来的流程中,主线程提交完任务后就阻塞等待了,浪费了主线程的线程资源,可利用主线程的资源,当阻塞队列满了,让主线程来执行当前任务,充分利用主线程的资源

执行 并发量为5时,执行耗时为100ms左右,和原来参数表现基本一致

并发量为50时,执行耗时为100+ms左右,最高也只到150ms,且没有出现任何异常

并发量为500时,执行耗时为300+ms左右,最高也只到500+ms,且没有出现任何异常

相关推荐
2401_857622661 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589361 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没2 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码4 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries5 小时前
读《show your work》的一点感悟
后端
A尘埃5 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23075 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code5 小时前
(Django)初步使用
后端·python·django
代码之光_19805 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端