springcloud配置中心nacos动态线程池Dynamic-tp配置接入实战

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情

最近业务上需要把项目组几个微服务接入动态线程池框架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 注解

image.png

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

image.png

2、阻塞队列只有VariableLinkedBlockingQueue类型可以修改capacity,该类型功能和 LinkedBlockingQueue相似,只是capacity不是final类型,可以修改。

3、配置企微机器人地址KEY

platform: wechat
urlKey: 3a700-127-4bd-a798-c53d8b69c     # 机器人地址后的key
receivers: test1                         # 指定接收人企微名称,默认@所有人
      
复制代码

机器人配置参考企微webhook

4、重要类DtpBeanDefinitionRegistrar配置转换

image.png

猜你喜欢

转载自juejin.im/post/7178394844937601080