美团动态线程池,真香啊!

360影视 2025-01-13 16:41 2

摘要:代码中创建了一个 ThreadPoolExecutor,但是不知道那几个核心参数设置多少比较合适凭经验设置参数值,上线后发现需要调整,改代码重启服务,非常麻烦线程池相对开发人员来说是个黑盒,运行情况不能及时感知到,直到出现问题

使用线程池 ThreadPoolExecutor 过程中你是否有以下痛点呢?

代码中创建了一个 ThreadPoolExecutor,但是不知道那几个核心参数设置多少比较合适凭经验设置参数值,上线后发现需要调整,改代码重启服务,非常麻烦线程池相对开发人员来说是个黑盒,运行情况不能及时感知到,直到出现问题

如果你有以上痛点,动态可监控线程池(DynamicTp)或许能帮助到你。

如果看过 ThreadPoolExecutor 的源码,大概可以知道它对核心参数基本都有提供 set/get 方法以及一些扩展方法,可以在运行时动态修改、获取相应的值。

现在大多数的互联网项目其实都会微服务化部署,有一套自己的服务治理体系,微服务组件中的分布式配置中心扮演的就是动态修改配置, 实时生效的角色。那么我们是否可以结合配置中心来做运行时线程池参数的动态调整呢?

答案是肯定的,而且配置中心相对都是高可用的, 使用它也不用过于担心配置推送出现问题这类事儿,而且也能减少研发动态线程池组件的难度和工作量。

基于以上背景分析,我们对线程池 ThreadPoolExecutor 做一些扩展增强,主要实现以下目标

框架功能大体可以分为以下几个模块

配置变更监听模块服务内部线程池管理模块三方组件线程池管理模块监控模块通知告警模块adapter 模块:主要是适配一些第三方组件的线程池管理,目前已经实现的有 SpringBoot 内置的三大 web 容器(Tomcat、Jetty、Undertow)、Dubbo、RocketMq、Hystrix、Grpc 的线程池管理, 后续会接入其他常用组件的线程池管理。common 模块:主要是一些各个模板都会用到的类,解耦依赖,复用代码,大家日常开发中可能也经常会这样做。core 模块:该框架的核心代码都在这个模块里,包括动态调整参数,监控报警,以及串联整个项目流程都在此。example 模块:提供一个简单使用示例,方便使用者参照extension 模块:放一些扩展功能实现,比如基于 redis 的流控扩展、邮件发送扩展、skywalking 上下文传递扩展等logging 模块:用于配置框架内部日志的输出,目前主要用于输出线程池监控指标数据到指定文件starter模块:提供独立功能模块的依赖封装、自动配置等相关。

1.监听特定配置中心的指定配置文件(已实现 Nacos、Apollo、Zookeeper、Consul、Etcd),可通过内部提供的SPI接口扩展其他实现。插播一条:如果你想加入我们,可以点击->程序员交流社区

2.解析配置文件内容,内置实现 yml、properties、json 配置文件的解析,可通过内部提供的 SPI 接口扩展其他实现

3.通知线程池管理模块实现参数的刷新

1.服务启动时从配置中心拉取配置,生成线程池实例注册到内部线程池注册中心以及 Spring 容器中

2.接受配置监听模块的刷新事件,实现线程池参数的刷新

3.代码中通过依赖注入(推荐)或者 DtpRegistry.getDtpExecutor 方法根据线程池名称来获取线程池实例

1.服务启动获取第三方中间件的线程池,被框架管理起来

2.接受参数刷新、指标收集、通知报警事件,进行相应的处理

监控模块

实现监控指标采集以及输出,默认提供以下三种方式,也可通过内部提供的 SPI 接口扩展其他实现

默认实现 JsonLog 输出到磁盘,可以自己采集解析日志,存储展示MicroMeter采集,引入 MicroMeter 相关依赖,暴露相关端点,采集指标数据,结合 Grafana 做监控大盘暴雷自定义 Endpoint 端点(dynamic-tp),可通过 http 方式实时访问通知告警模块

对接办公平台,实现通知告警功能,已支持钉钉、企微、飞书、邮件,可通过内部提供的 SPI 接口扩展其他实现,通知告警类型如下

线程池主要参数变更通知阻塞队列容量达到设置的告警阈值线程池活性达到设置的告警阈值触发拒绝策略告警,格式:A/B,A:该报警项前后两次报警区间累加数量,B:该报警项累计总数任务执行超时告警,格式:A/B,A:该报警项前后两次报警区间累加数量,B:该报警项累计总数任务等待超时告警,格式:A/B,A:该报警项前后两次报警区间累加数量,B:该报警项累计总数

来源:散文随风想

相关推荐