线程池在业务中的实践

1. 业务背景

  • 场景一: 快速响应用户请求
    场景描述:比如说⽤户要查看⼀个商品的信息,那么我们需要将商品维度的⼀系列信息如商品的价格优惠库存图⽚等等聚合起来,展示给⽤户。
    分析:从用户角度来看,要求响应越快越还,但其实这些面向用户功能的聚合通常会伴随着调用之间的级联、,这种情况下使用线程池,将调用封装成任务并行执行,缩短总体的响应时间,这种场景其实最重要的就是获取最大的响应速度去满足用户,所以应该不设置队列去缓冲并发任务。调高corePoolSize和maxPoolSize去尽可能创造多的线程快速执行任务。
  • 场景二: 快速处理批量任务
    场景描述:比如说有一个离线的计算任务计算量很大,像大型的统计报表,其实我们希望的是来快速生成报表
    分析:这种需要执行大量任务,我们希望任务执行的越快越好,使用多线程。但这种与响应速度的区别在于:这类场景任务量巨大,并不需要瞬时完成,而是关注如何使用有限的资源尽可能在单位时间处理更多的任务,也就是强调吞吐量。这种情况下应该设置队列去缓冲并发任务,调整合适的corePoolSize,这里,设置的线程数过多可能会引发线程上下文切换频繁,也会降低处理任务的速度,减低吞吐量。

2. 实际问题及方案思考

线程池使用面临的核心问题在于:线程池的参数不好配置:线程池执行的情况和任务类型相关性很大,IO、cpu密集型任务执行起来的情况差异非常大。

事故描述一:xxx 页面展示接口大量调用降级:队列设置正常,核心线程过小
事故原因:该服务展示接口内部逻辑使用线程池并行计算,由于没有预估好调用的流量,导致最大核心数设置偏小,大量抛出RejectedExecutionException,触发接口降低。

事故描述二:服务不可用:任务堆积,线程池队列⻓度设置过⻓、corePoolSize设置过⼩导致任务执⾏速度低;线程来不及处理任务造成大量任务堆积,导致任务执行时间过长,会导致下游服务的大量调用超时失败。

思考:那线程池参数有计算呢公式吗?
其实很难有一个准确的公式来计算出核心线程、最大线程数的,往往实际场景是根据压测、tps等来大概估算的,但实际中有时候流量是正常的,有时候流量往往是随机的,其实也不符合实际场景,那既然不能一下子算出来,那可以通过动态线程池参数,实现参数的动态化。
那问题来了:怎样将修改线程池参数的成本降下来?
在成本可控的情况下,在发生故障时可以快速调整从而缩短故障恢复的时间?如何缩短时间?线程池参数的动态感知------> 分布式配置中心,实现线程池参数动态配置即时生效。在这里插入图片描述

线程池参数动态化:分布式配置中心,参数的更新。

3. 动态线程池

动态调参:JDK提供的原生的ThreadPoolExecutor提供了对核心线程数、最大线程数、拒绝策略等的set方法,在运行期使用方调用此方法设置corePoolSize之后,线程池会直接覆盖原来的corePoolSize值,并且会基于当前值和原始值的比较结果采取不同的处理策略。对于当前值小于当前工作线程的情况,说明有多余的工作线程,这时会向工作线程发起中断请求以实现回收;对于当前值大于原始值并且队列中有待执行任务,则线程池会创建新的工作线程来执行队列任务。

那怎样实现动态线程池:获取到当前程序中的ThreadPoolExecutor实例------> 进而获取到当前程序的线程池参数-----> 之后上报到redis中,基于redis发布订阅,实现动态参数更新。

对于JDK提供的这些set方法,线程池内部会处理好当前状态做到平滑处理。只要维护ThreadPoolExecutor实例,在需要修改的时候修改参数即可。

3.1 遇到的问题

问题一:实际投入项目使用时,使用redis作为线程池的注册中心,项目本身是不是还需要额外定义redis客户端实例?要和starter里面的实例 区分开来使用?

  • @ConditionalOnMissingBean。

问题二:为什么redisson 定义的时候 不用默认的配置,而是自己定义的redis的配置类

  • 自己定义可以更好控制和扩展,不会受到升级影响。

问题三:如果想这个starter 既要支持redis 又要支持nacos?

  • 组件中,如果有多个,之后有需要部分不启动。可以用 class.forName 进行检测,如果类不存在就不检测了。还可以使用@ConditionalOnMissingBean的方式,注入的对象也可以控制。

4. 代码

首先要将本地采集到的线程池数据进行上报,采用redis作为注册中心,将采集到的线程池配置信息上传到redis(这是是用spring定时任务,定时采集线程池配置信息进行上报的);动态更新线程池配置参数,是根据redis发布订阅来实现的,将需要动态更新的消息发布到topic,在消费者这一端(订阅了该topic)就会监听到这个消息,然后将变更的消息设置到当前应用的对应的ThreadPoolExecutor实例上(应用本地有一个Map<String, ThreadPoolExecutor>, key为线程池实例bean的名字,value为线程池实例,拿到的消息包含哪个应用啊、哪个线程池实例啊、以及要设置的参数:核心线程、最大线程;用消息中线程池实例bean的名字拿到对应的实例,然后直接更新这个实例中的核心线程、最大线程、队列长度等信息,实现动态更新,不需要重启应用)。

问:spring采集线程池配置信息怎么做的?
Map<String, ThreadPoolExecutor> threadPoolExecutorMap;就拿到了当前应用中的所有线程池实例。

上报到redis中的信息包括什么:包括线程池的名字、标识、配置参数。

在探索智慧旅游的新纪元,一个集科技、创新与服务于一体的整体解决方案正悄然改变着我们的旅行方式。智慧旅游,作为智慧城市的重要分支,旨在通过新一代信息技术,如云计算、大数据、物联网等,为游客、旅游企业及政府部门提供无缝对接、高效互动的旅游体验与管理模式。这一方案不仅重新定义了旅游行业的服务标准,更开启了旅游业数字化转型的新篇章。 智慧旅游的核心在于“以人为本”,它不仅仅关注技术的革新,更注重游客体验的提升。从游前的行程规划、信息查询,到游的智能导航、个性化导览,再到游后的心情分享、服务评价,智慧旅游通过构建“一云多屏”的服务平台,让游客在旅游的全过程都能享受到便捷、个性化的服务。例如,游客可以通过手机APP轻松定制专属行程,利用智能语音导览深入了解景点背后的故事,甚至通过三维GIS地图实现虚拟漫游,提前感受目的地的魅力。这些创新服务不仅增强了游客的参与感和满意度,也让旅游变得更加智能化、趣味化。 此外,智慧旅游还为旅游企业和政府部门带来了前所未有的管理变革。通过大数据分析,旅游企业能够精准把握市场动态,实现旅游产品的精准营销和个性化推荐,从而提升市场竞争力。而政府部门则能利用智慧旅游平台实现对旅游资源的科学规划和精细管理,提高监管效率和质量。例如,通过实时监控和数据分析,政府可以迅速应对旅游高峰期的客流压力,有效预防景区超载,保障游客安全。同时,智慧旅游还促进了跨行业、跨部门的数据共享与协同合作,为旅游业的可持续发展奠定了坚实基础。总之,智慧旅游以其独特的魅力和无限潜力,正引领着旅游业迈向一个更加智慧、便捷、高效的新时代。
内容概要:本文详细介绍了大模型的发展现状与未来趋势,尤其聚焦于DeepSeek这一创新应用。文章首先回顾了人工智能的定义、分类及其发展历程,指出从摩尔定律到知识密度提升的转变,强调了大模型知识密度的重要性。随后,文章深入探讨了DeepSeek的发展路径及其核心价值,包括其推理模型、思维链技术的应用及局限性。此外,文章展示了DeepSeek在多个行业的应用场景,如智能客服、医疗、金融等,并分析了DeepSeek如何赋能个人发展,具体体现在公文写作、文档处理、知识搜索、论文写作等方面。最后,文章展望了大模型的发展趋势,如通用大模型与垂域大模型的协同发展,以及本地部署小模型成为主流应用渠道的趋势。 适合人群:对人工智能和大模型技术感兴趣的从业者、研究人员及希望利用DeepSeek提升工作效率的个人用户。 使用场景及目标:①了解大模型技术的最新进展和发展趋势;②掌握DeepSeek在不同领域的具体应用场景和操作方法;③学习如何通过DeepSeek提升个人在公文写作、文档处理、知识搜索、论文写作等方面的工作效率;④探索大模型在特定行业的应用潜力,如医疗、金融等领域。 其他说明:本文不仅提供了理论知识,还结合实际案例,详细介绍了DeepSeek在各个场景下的应用方式,帮助读者更好地理解和应用大模型技术。同时,文章也指出了当前大模型技术面临的挑战,如模型的局限性和数据安全问题,鼓励读者关注技术的持续改进和发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值