无题
无题
赵海波title: 动态线程池组件:项目总结
date: 2024/9/6
categories: 项目
tag:
- 后端开发
- 组件
- 项目
- 线程池
cover: https://jsd.onmicrosoft.cn/gh/youdekangkang/blogImage@main/img/image-20240906034412240.png
组件的特点?
因为任务会分为CPU密集型以及IO密集型,每一种方案都会需要不同的场景配置,但是你又不能保证所有的配置都是最优值。所以既然不能保证参数配置最合理,那么是否可以通过将修改线程池参数的成本降下来,这样⾄少可以发⽣故障的时候可以快速 调整从⽽缩短故障恢复的时间?基于这个思考,我们可以将线程池的参数从代码中迁移到注册中心上, 实现线程池参数可动态配置和即时⽣效。
为什么要自研线程池?
问题1:为什么要自研?
这是很典型的问题,很多人也会比较奇怪为什么放着好的成熟的方案不适用非要自己写一套东西。以下便是自己写组件的好处:
1.满足特定需求: 自研可以更精准地匹配内部业务场景,定制化功能以满足特定的业务需求。 成熟的实现可能无法覆盖所有细节,自研可以填补这些空白。
2.技术可控: 自研可以更好地控制技术栈,避免对第三方库的过度依赖,降低外部因素(如库的废弃或更新不兼容) 带来的风险。 可以确保代码的质量和安全性,符合组织的编码标准和安全规范。
3.性能优化: 自研允许针对具体环境进行性能优化,提高系统效率。 有时,现成的解决方案可能无法达到所需的性能要求,自研可以解决这个问题。
4.知识产权: 自研技术可以积累公司的核心竞争力,形成专有知识产权。 这有助于保护公司的商业秘密,防止技术泄露。
5.降低成本: 长期来看,自研可能减少对第三方服务的费用支出,尤其是当需要大规模使用时。 自研也可以根据内部资源进行调整,减少不必要的外部成本。
6.创新能力: 自研鼓励创新,推动技术团队的成长,提高整体技术水平。 它允许尝试新的设计和算法,可能产生突破性的技术进步。
7.灵活性和可扩展性: 自研使团队能够灵活调整架构,以适应未来的变化。 它通常更便于与现有系统集成,增强系统的可扩展性。
问题2:你的线程池方案相较于成熟的方案(以美图的dynamic-up为例)相比都有什么好处以及改进?
主要就是轻量化,自定义常用参数,更加满足特殊项目组的需求
项目内容
这是我们项目中存在的结构
首先要知道组件中存在的三个项目分别是SDK => starter 项目,线程池管理 => admin 项目,业务项目 AB => test 项目
关于线程池工作原理
1.线程池的配置数据是怎么采集的?
线程池在创建的时候已经用 @Bean 注解,所以 Spring 会将其自动自动注入到 threadPoolExecutorMap 中。
2.更新线程池的配置数据是怎么完成的?
如图业务项目中部署的 SDK 中会订阅 Redis 的 Topic,线程池管理项目(admin)会发布数据到 topic 中,SDK 会感知到数据变化,进而 update 业务项目中的线程池。
3.怎么解决线程池数据重复上报到 Redis ?
原代码中所有线程池的配置是保存在 Redis 的 List 结构中的,List 不会进行去重处理
初始化先创建线程池(AB测试中创建了两个线程池)
首先ThreadConfig类通过ThreadPoolConfigProperties导入线程池的配置,然后创建出线程池类ThreadPoolExecutor。这个提供出一个Bean供给Spring框架中的其他类进行配置使用。
最核心的类是DynamicThreadPoolAutoConfig,他在初始化时统一创建Redis注册功能,监听,线程池服务以及上报功能的Bean
其中比较重要的是发布订阅相关的类,
后续要做能够和前端链通实现动态地去更新这两个线程池的配置参数
佬总结的:
步骤1: 创建DynamicThreadPoolAutoConfig类,这是Spring Boot的自动配置类,用于初始化和配置动态线程池。 在DynamicThreadPoolAutoConfig类中,定义了多个Bean,包括redissonClient、redisRegistry、dynamicThreadPoolService、threadPoolDataReportJob、threadPoolConfigAdjustListener和dynamicThreadPoolRedisTopic。这些Bean分别用于创建Redis客户端,注册中心,动态线程池服务,线程池数据报告任务,线程池配置调整监听器和Redis主题。
a、redissonClient Bean用于创建Redis客户端,用于与Redis服务器进行通信。
b、redisRegistry Bean用于创建注册中心,用于报告线程池的状态。
c、dynamicThreadPoolService Bean用于创建动态线程池服务,用于管理线程池。
d、threadPoolDataReportJob Bean用于创建线程池数据报告任务,用于定期向注册中心报告线程池的状态。
e、threadPoolConfigAdjustListener Bean用于创建线程池配置调整监听器,用于监听Redis主题上的消息,当收到消息时,调整线程池的配置。
f、dynamicThreadPoolRedisTopic Bean用于创建Redis主题,用于发布和订阅消息。
步骤2:创建IRegistry接口,定义了报告线程池的方法。 创建RedisRegistry类,实现了IRegistry接口,使用Redis作为注册中心,实现了报告线程池的方法。
步骤3: 创建DynamicThreadPoolService类,用于管理线程池,包括获取线程池的状态,调整线程池的配置等。
步骤4: 创建ThreadPoolDataReportJob类,用于定期向注册中心报告线程池的状态; 创建ThreadPoolConfigAdjustListener类,用于监听Redis主题上的消息,当收到消息时,调整线程池的配置。
步骤5: 启动自动配置 resources/META-INF/spring.factories
a、在application-dev.yml文件中,配置了线程池的参数,包括核心线程数,最大线程数,保持活动时间,阻塞队列大小,拒绝策略等。
b、在spring.factories文件中,配置了自动配置类DynamicThreadPoolAutoConfig,Spring Boot在启动时,会自动加载这个类,初始化和配置动态线程池。 org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.bugstack.middleware.dynamic.thread.pool.sdk.config.DynamicThreadPoolAutoConfig @EnableAutoConfiguration 的作用是从 classpath 中搜索所有 META-INF/spring.factories 配置文件然后将其中 org.springframework.boot.autoconfigure.EnableAutoConfiguration 配置的信息加载到 spring 容器。
可以考虑后续的升级拓展:首页 | dynamictp