最近业务上需要把项目组几个微服务接入动态线程池框架Dynamic-tp监控,同时支持webhook机器人接受变更通知、容量报警、活性报警、拒绝报警、任务超时报警等通知,方便项目组同事企业微信群实时监控线程池状态,动态调整线程参数。
接手开始上手,一看网上教程和demo很多啊,心中窃喜,一顿ctrl+c+v大发,却发现告警不通知,配置线程池不生效,数着承诺的交付时间,开始发慌;几经周折,才定,斯文于记。
一、接入步骤
1、引入POM文件
spring-cloud场景下的nacos应用接入用此依赖:
<dependency>
<groupId>cn.dynamictp</groupId>
<artifactId>dynamic-tp-spring-cloud-starter-nacos</artifactId>
<version>1.0.8</version>
</dependency>
复制代码
非spring-cloud 场景下的nacos应用接入用此依赖:
<dependency>
<groupId>cn.dynamictp</groupId>
<artifactId>dynamic-tp-spring-boot-starter-nacos</artifactId>
<version>1.0.8</version>
</dependency>
2、启动类加 @EnableDynamicTp 注解
3、配置中心配置线程池yml实例
spring:
dynamic:
tp:
enabled: true
enabledBanner: true # 是否开启banner打印,默认true
enabledCollect: true # 是否开启监控指标采集,默认false
collectorTypes: micrometer,logging # 监控数据采集器类型(logging | micrometer | internal_logging),默认micrometer
logPath: /home/logs # 监控日志数据路径,默认 ${user.home}/logs,采集类型非logging不用配置
monitorInterval: 5 # 监控时间间隔(报警判断、指标采集),默认5s
nacos: # nacos配置,不配置有默认值(规则appname-dev.yml这样),cloud应用不需要配置
dataId: dynamic-tp-demo-dev.yml
group: DEFAULT_GROUP
apollo: # apollo配置,不配置默认拿apollo配置第一个namespace
namespace: dynamic-tp-demo-dev.yml
configType: yml # 配置文件类型,非cloud nacos 和 apollo需配置,其他不用配
platforms: # 通知报警平台配置
- platform: wechat
urlKey: 3a700-127-4bd-a798-c53d8b69c # 替换
receivers: test1,test2 # 接受人企微名称
- platform: ding
urlKey: f80dad441fcd655438f4a08dcd6a # 替换
secret: SECb5441fa6f375d5b9d21 # 替换,非sign模式可以没有此值
receivers: 18888888888 # 钉钉账号手机号
- platform: lark
urlKey: 0d944ae7-b24a-40 # 替换
receivers: test1,test2 # 接受人飞书名称/openid
tomcatTp: # tomcat webserver线程池配置
corePoolSize: 100
maximumPoolSize: 200
keepAliveTime: 60
jettyTp: # jetty weberver线程池配置
corePoolSize: 100
maximumPoolSize: 200
undertowTp: # undertow webserver线程池配置
corePoolSize: 100
maximumPoolSize: 200
keepAliveTime: 60
hystrixTp: # hystrix 线程池配置
- threadPoolName: hystrix1
corePoolSize: 100
maximumPoolSize: 200
keepAliveTime: 60
dubboTp: # dubbo 线程池配置
- threadPoolName: dubboTp#20880 # 名称规则:dubboTp + "#" + 协议端口
threadPoolAliasName: 测试线程池 # dubbo线程池
corePoolSize: 100
maximumPoolSize: 200
keepAliveTime: 60
notifyItems: # 报警项,不配置自动会按默认值配置(变更通知、容量报警、活性报警)
- type: capacity # 报警项类型,查看源码 NotifyTypeEnum枚举类
enabled: true
threshold: 80 # 报警阈值
platforms: [ding,wechat] # 可选配置,不配置默认拿上层platforms配置
interval: 120 # 报警间隔(单位:s)
rocketMqTp: # rocketmq 线程池配置
- threadPoolName: group1#topic1 # 名称规则:group + "#" + topic
corePoolSize: 200
maximumPoolSize: 200
keepAliveTime: 60
executors: # 动态线程池配置
- threadPoolName: dtpExecutor1
threadPoolAliasName: 测试线程池 # 线程池别名
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)
- type: change
enabled: true
- type: liveness
enabled: true
threshold: 80
- type: reject
enabled: true
threshold: 1
- type: run_timeout
enabled: true
threshold: 1
- type: queue_timeout
enabled: true
threshold: 1
服务启动时会根据配置中心的配置[dtpExecutor1]动态注册到Spring容器中。
4、配置线程池使用
@Resource或@Autowired进行依赖注入,或通过
DtpRegistry.getDtpExecutor("name")获取。
@Resource
private ThreadPoolExecutor dtpExecutor1;
DtpExecutor dtpExecutor = DtpRegistry.getDtpExecutor("dtpExecutor1");
dtpExecutor.execute(() -> System.out.println("test"));
以上4步,顺利话可以接入使用了:
| __ \ (_) |__ __|
| | | |_ _ _ __ __ _ _ __ ___ _ ___| |_ __
| | | | | | | '_ \ / _` | '_ ` _ | |/ __| | '_ \
| |__| | |_| | | | | (_| | | | | | | | (__| | |_) |
|_____/ __, |_| |_|__,_|_| |_| |_|_|___|_| .__/
__/ | | |
|___/ |_|
:: Dynamic Thread Pool ::
DynamicTp register dtpExecutor, source: beanPostProcessor, executor: DtpMainPropWrapper(dtpName=dynamic-tp-test-1, corePoolSize=6, maxPoolSize=8, keepAliveTime=50, queueType=VariableLinkedBlockingQueue, queueCapacity=200, rejectType=RejectedCountableCallerRunsPolicy, allowCoreThreadTimeOut=false)
DtpRegistry initialization end, remote dtpExecutors: [dtpExecutor1, dtpExecutor2], local dtpExecutors: [ioIntensiveExecutor], local commonExecutors: [commonExecutor]
启动日志出现, remote dtpExecutors便是配置注册的线程池了,那么恭喜。
当然我们也可以在程序中定义线程池代替配置文件,但是官方不推荐,官方推荐的配置文件配置。普通 JUC线程池想要被监控,可以@Bean定义时加 @DynamicTp 注解。
* 1、 (ThreadPoolExecutor) Executors.newFixedThreadPool(1)加@DynamicTp("commonExecutor")
* 2、ThreadPoolCreator.createDynamicFast("dynamic-tp-test-1");
* 3、ThreadPoolBuilder.newBuilder()
二、避坑指南
1、yaml配置单独文件,不同的nacos配置可能会有差异,以nacos 2.0.2为例: 配置文件添加后缀.yml或者.yaml
2、阻塞队列只有
VariableLinkedBlockingQueue类型可以修改capacity,该类型功能和 LinkedBlockingQueue相似,只是capacity不是final类型,可以修改。
3、配置企微机器人地址KEY
platform: wechat
urlKey: 3a700-127-4bd-a798-c53d8b69c # 机器人地址后的key
receivers: test1 # 指定接收人企微名称,默认@所有人
机器人配置参考企微webhook
4、重要类
DtpBeanDefinitionRegistrar配置转换