Dromara【新晋开源项目】DynamicTp,美团动态线程池思路的实践!
快讯,开源轻量级动态线程池监控 - DynamicTp 加入Dromara社区!欢迎欢迎!!
下面是DynamicTp作者对DynamicTp的介绍。
大家好,今天我们来聊一个比较实用的话题,动态可监控的线程池实践,全新开源项目(DynamicTp)地址在文章末尾,欢迎交流学习。
背景
使用 ThreadPoolExecutor 过程中你是否有以下痛点呢?
1.代码中创建了一个 ThreadPoolExecutor,但是不知道那几个核心参数设置多少比较合适
2.凭经验设置参数值,上线后发现需要调整,改代码重启服务,非常麻烦
3.线程池相对开发人员来说是个黑盒,运行情况不能感知到,直到出现问题
如果你有以上痛点,动态可监控线程池(DynamicTp)或许能帮助到你。
如果看过 ThreadPoolExecutor 的源码,大概可以知道其实它有提供一些 set 方法,可以在运行时动态去修改相应的值,这些方法有:
public void setCorePoolSize(int corePoolSize); public void setMaximumPoolSize(int maximumPoolSize); public void setKeepAliveTime(long time, TimeUnit unit); public void setThreadFactory(ThreadFactory threadFactory); public void setRejectedExecutionHandler(RejectedExecutionHandler handler);
现在大多数的互联网项目其实都会微服务化部署,有一套自己的服务治理体系,微服务组件中的分布式配置中心扮演的就是动态修改配置, 实时生效的角色。那么我们是否可以结合配置中心来做运行时线程池参数的动态调整呢?答案是肯定的,而且配置中心相对都是高可用的, 使用它也不用过于担心配置推送出现问题这类事儿,而且也能减少研发动态线程池组件的难度和工作量。
综上,我们总结出以下的背景
-
广泛性:在 Java 开发中,想要提高系统性能,线程池已经是一个 90%以上的人都会选择使用的基础工具
-
不确定性:项目中可能会创建很多线程池,既有 IO 密集型的,也有 CPU 密集型的,但线程池的参数并不好确定;需要有套机制在运行过程中动态去调整参数
-
无感知性,线程池运行过程中的各项指标一般感知不到;需要有套监控报警机制在事前、事中就能让开发人员感知到线程池的运行状况,及时处理
-
高可用性,配置变更需要及时推送到客户端;需要有高可用的配置管理推送服务,配置中心是现在大多数互联网系统都会使用的组件,与之结合可以大幅度减少开发量及接入难度
简介
我们基于配置中心对线程池 ThreadPoolExecutor 做一些扩展,实现对运行中线程池参数的动态修改,实时生效; 以及实时监控线程池的运行状态,触发设置的报警策略时报警,报警信息会推送办公平台(钉钉、企微等)。 报警维度包括(队列容量、线程池活性、拒绝触发、任务超时等);同时也会定时采集线程池指标数据供监控平台可视化使用。 使我们能时刻感知到线程池的负载,根据情况及时调整,避免出现问题影响线上业务。
| __ \ (_) |__ __| | | | |_ _ _ __ __ _ _ __ ___ _ ___| |_ __ | | | | | | | '_ \ / _` | '_ ` _ | |/ __| | '_ \ | |__| | |_| | | | | (_| | | | | | | | (__| | |_) | |_____/ __, |_| |_|__,_|_| |_| |_|_|___|_| .__/ __/ | | | |___/ |_| :: Dynamic Thread Pool ::
特性
-
参考美团线程池实践,对线程池参数动态化管理,增加监控、报警功能
-
基于 Spring 框架,现只支持 SpringBoot 项目使用,轻量级,引入 starter 即可使用
-
基于配置中心实现线程池参数动态调整,实时生效;集成主流配置中心,已支持 Nacos、Apollo、Zookeeper、Consul, 同时也提供 SPI 接口可自定义扩展实现
-
内置通知报警功能,提供多种报警维度(配置变更通知、活性报警、容量阈值报警、拒绝触发报警、任务执行或等待超时报警), 默认支持企业微信、钉钉报警,同时提供 SPI 接口可自定义扩展实现
-
内置线程池指标采集功能,支持通过 MicroMeter、JsonLog 日志输出、Endpoint 三种方式,可通过 SPI 接口自定义扩展实现
-
集成管理常用第三方组件的线程池,已集成 SpringBoot 内置 WebServer(Tomcat、Undertow、Jetty)的线程池管理
-
提供任务包装功能,实现TaskWrapper接口即可,如TtlTaskWrapper可以支持线程池上下文信息传递
-
JUC普通线程池也可以被框架监控(@DynamicTp);参考Tomcat线程池提供了io密集型场景使用的EagerDtpExecutor
架构设计
主要分四大模块
-
配置变更监听模块:
1.监听特定配置中心的指定配置文件(已实现 Nacos、Apollo、Zookeeper、Consul),可通过内部提供的SPI接口扩展其他实现
2.解析配置文件内容,内置实现 yml、properties 配置文件的解析,可通过内部提供的 SPI 接口扩展其他实现
3.通知线程池管理模块实现刷新
-
线程池管理模块:
1.服务启动时从配置中心拉取配置,生成线程池实例注册到内部线程池注册中心以及Spring容器中
2.监听模块监听到配置变更时,将变更信息传递给管理模块,实现线程池参数的刷新
3.代码中通过依赖注入(推荐)或者getExecutor()方法根据线程池名称来获取线程池实例
-
监控模块:
实现监控指标采集以及输出,默认提供以下三种方式,也可通过内部提供的 SPI 接口扩展其他实现
1.默认实现JsonLog输出到磁盘,可以自己采集解析日志,存储展示
2.MicroMeter采集,引入 MicroMeter 相关依赖,暴露相关端点
3.暴雷自定义Endpoint端点,可通过 http 方式实时访问
-
通知告警模块:
对接办公平台,实现通知告警功能,默认实现钉钉、企微,可通过内部提供的 SPI 接口扩展其他实现,通知告警类型如下
1.线程池主要参数变更通知
2.阻塞队列容量达到设置的告警阈值
3.线程池活性达到设置的告警阈值
4.触发拒绝策略告警,格式:A/B,A:该报警项前后两次报警区间累加数量,B:该报警项累计总数
5.任务执行超时告警,格式:A/B,A:该报警项前后两次报警区间累加数量,B:该报警项累计总数
6.任务等待超时告警,格式:A/B,A:该报警项前后两次报警区间累加数量,B:该报警项累计总数
使用
1.引入对应配置中心的依赖
2.配置中心配置线程池实例,配置参考下文(给出的是全配置项,配置项都有默认值)
3.启动类加@EnableDynamicTp注解
4.使用@Resource或@Autowired注解注入,或通过DtpRegistry.getExecutor("name")获取
5.普通JUC线程池想要被监控,可以@Bean定义时加@DynamicTp注解
6.tips:动态线程池实例服务启动时会根据配置中心的配置动态注册到Spring容器中,建议不要用@Bean编程式重复声明同一线程池实例,直接配置在配置中心就行
7.详细参考Example示例
-
线程池配置(yml 类型)
spring: dynamic: tp: enabled: true enabledBanner: true # 是否开启banner打印,默认true enabledCollect: false # 是否开启监控指标采集,默认false collectorType: logging # 监控数据采集器类型(JsonLog | MicroMeter),默认logging logPath: /home/logs # 监控日志数据路径,默认 ${user.home}/logs monitorInterval: 5 # 监控时间间隔(报警判断、指标采集),默认5s platforms: # 通知报警平台配置 - platform: wechat urlKey: 3a7500-1287-4bd-a798-c5c3d8b69c # 替换 receivers: test1,test2 # 接受人企微名称 - platform: ding urlKey: f80dad441fcd655438f4a08dcd6a # 替换 secret: SECb5441fa6f375d5b9d21 # 替换,非sign模式可以没有此值 receivers: 15810119805 # 钉钉账号手机号 tomcatTp: # tomcat web server线程池配置 minSpare: 100 max: 400 jettyTp: # jetty web server线程池配置 min: 100 max: 400 undertowTp: # undertow web server线程池配置 coreWorkerThreads: 100 # 核心线程数 maxWorkerThreads: 400 # 最大线程数 workerKeepAlive: 40 executors: # 动态线程池配置,都有默认值,采用默认值的可以不配置该项,减少配置量 - threadPoolName: dtpExecutor1 executorType: common # 线程池类型common、eager:适用于io密集型 corePoolSize: 6 maximumPoolSize: 8 queueCapacity: 200 queueType: VariableLinkedBlockingQueue # 任务队列,查看源码QueueTypeEnum枚举类 rejectedHandlerType: CallerRunsPolicy # 拒绝策略,查看RejectedTypeEnum枚举类 keepAliveTime: 50 allowCoreThreadTimeOut: false threadNamePrefix: test # 线程名前缀 waitForTasksToCompleteOnShutdown: false # 参考spring线程池设计 awaitTerminationSeconds: 5 # 单位(s) preStartAllCoreThreads: false # 是否预热核心线程,默认false runTimeout: 200 # 任务执行超时阈值,目前只做告警用,单位(ms) queueTimeout: 100 # 任务在队列等待超时阈值,目前只做告警用,单位(ms) taskWrapperNames: ["ttl"] # 任务包装器名称,集成TaskWrapper接口 notifyItems: # 报警项,不配置自动会按默认值配置(变更通知、容量报警、活性报警、拒绝报警、任务超时报警) - type: capacity # 报警项类型,查看源码 NotifyTypeEnum枚举类 enabled: true threshold: 80 # 报警阈值 platforms: [ding,wechat] # 可选配置,不配置默认拿上层platforms配置的所以平台 interval: 120 # 报警间隔(单位:s)
-
代码调用,从DtpRegistry中根据线程池名称获取,或者通过依赖注入方式(推荐,更优雅)
@Resource private ThreadPoolExecutor dtpExecutor1; public void exec() { dtpExecutor1.execute(() -> System.out.println("test")); }
public static void main(String[] args) { DtpExecutor dtpExecutor = DtpRegistry.getExecutor("dtpExecutor1"); dtpExecutor.execute(() -> System.out.println("test")); }
-
详细使用实例参考
example
工程
通知报警
-
触发报警阈值会推送相应报警消息(活性、容量、拒绝、超时),且会高亮显示相应字段
-
配置变更会推送通知消息,且会高亮变更的字段
监控
监控数据
通过 collectType 属性配置监控指标采集类型,默认 logging
-
MicroMeter:通过引入相关 MicroMeter 依赖采集到相应的平台 (如 Prometheus,InfluxDb...)
-
Logging:定时采集指标数据以 Json 日志格式输出磁盘,地址 {appName}.monitor.log
-
暴露 EndPoint 端点(dynamic-tp),可以通过 http 方式请求
[ { "dtp_name": "remoting-call", "core_pool_size": 6, "maximum_pool_size": 12, "queue_type": "SynchronousQueue", "queue_capacity": 0, "queue_size": 0, "fair": false, "queue_remaining_capacity": 0, "active_count": 0, "task_count": 21760, "completed_task_count": 21760, "largest_pool_size": 12, "pool_size": 6, "wait_task_count": 0, "reject_count": 124662, "reject_handler_name": "CallerRunsPolicy" } ]
关注项目
对项目有什么想法或者建议,可以创建issues,一起完善项目
仓库地址,欢迎给项目点赞!
https://github.com/dromara/dynamic-tp
https://gitee.com/dromara/dynamic-tp

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
SmartisanOS 官宣回归,将推出新品
SmartisanOS官博今日发文宣布回归,与大众分享了一些沉寂已久的SmartisanOS团队近况,并透露即将推出一款新品。 SmartisanOS(俗称锤子操作系统)是罗永浩创立的锤子科技推出的基于 Android 深度定制的系统,于 2013 年 3 月 27 日正式发布,2014 年 5 月 20 日发布Smartisan OS 1.0 版本。 Smartisan 释义:Smart+Artisan 组合创意词,意为智能机时代的精细工匠。Smartisan OS 主要搭载于坚果手机中。 公告称,“虽然暂时告别手机江湖,但我们并没有停止对 SmartisanOS 创新形态的探索,也没有放下对产品体验的追求。” 全文内容如下: 朋友们,好久不见。 很高兴又能像以前一样,在一款新品即将面世之前,与大家分享一些有关 SmartisanOS 团队的近况。虽然暂时告别手机江湖,但我们并没有停止对 SmartisanOS 创新形态的探索,也没有放下对产品体验的追求。 这几年,我们的生活方式发生了一些变化:在家用会议软件进行远程沟通、通过在线课堂保证学习进度。在客厅偶尔需要客串办公室和课堂甚至更...
- 下一篇
社区动态|Apache Doris 迎来第 300 位 Contributor !
亲爱的各位 Apache Doris 社区的小伙伴们,我们很高兴地告诉大家,Apache Doris Contributor 数量已经达到 300 了!感谢每一个让 Apache Doris 更好的你! 从 Apache Doris 开源到现在,我们一直对每一位为 Apache Doris 作出过贡献的社区小伙伴心存感激,正是因为有你的付出,才让 Apache Doris 一步一步成长到今天。展望未来,我们将持续努力、致力于把 Apache Doris 打造成世界顶级的分析型数据库产品,希望能帮助更多的社区用户解决数据分析的痛点,希望每一位小伙伴都能从社区中有所收获。 与此同时,我们也希望有更多的小伙伴们与我们一同成长。如果你想参与 Apache Doris 社区的交流和讨论,欢迎关注我们的 GitHub 代码仓库或者订阅邮件组 dev@doris.apache.org 。 GitHub 代码仓库 https://github.com/apache/incubator-doris dev 邮件组订阅 https://doris.apache.org/master/zh-CN/c...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Hadoop3单机部署,实现最简伪集群