目录

chen 的个人博客

VX:ZzzChChen
Phone:13403656751
Email:zxydczzs@gmail.com

X

Hippo4j动态线程池监控接入

简单了解

线程池痛点

原文摘录

线程池是一张基于池化思想管理线程的工具,使用线程池可以减少创建销毁线程的开销,避免线程过多导致系统资源耗尽。在高并发以及大批量的任务处理场景,线程池的使用是必不可少的。

如果有在项目中实际使用线程池,相信你可能会遇到一下痛点

  • 线程池随便定义,线程资源过多,造成服务器高负载;
  • 线程池参数不易评估,随着业务的并发提升,业务面临出现故障的风险;
  • 线程池任务执行时间超过平均时间,开发人员无法感知;
  • 线程池任务堆积,触发拒绝策略,影响既有业务正常运行;
  • 当业务出现超时、熔断等问题时,因为没有监控,无法确定是不是线程池引起;
  • 原生线程池不支持运行时变量的传递,比如 MDC 上下文遇到线程池就 GC。
  • 无法执行优雅关闭,当项目关闭时,大量正在运行的线程池任务被丢弃;
  • 线程池运行中,任务执行停止,怀疑发生死锁或执行耗时操作,但是无从下手;

如果同学们有以上的问题或者疑问,接着往下看。

什么是 Hippo4j

原文摘录

Hippo4j 通过对 JDK 线程池增强,以及扩展三方框架底层线程池等功能,为业务系统提高线上运行保障能力。

提供一下功能支持

  • 全局管控 - 管理应用线程池实例;
  • 动态变更 - 应用运行时动态变成线程池参数,包括不限于:核心、最大线程数、阻塞队列容量、拒绝策略等。
  • 通知报警 - 内置四种报警通知策略,线程池活跃度、容量水位、拒绝策略以及任务执行时间超长;
  • 运行监控 - 实时查看线程池运行时数据,最近半小时线程池运行数据图表展示;
  • 功能扩展 - 支持线程池任务传递上下文,项目关闭时,支持等待线程池在指定时间内完成任务;
  • 多种模式 - 内置两种使用模式:依赖配置中心 和 无中间件依赖。
  • 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更;
  • 框架适配 - Dubbo、Hystrix、RabbitMQ、RocketMQ 等消费线程池运行时数据查看和线程数变更。

正文

采用源码编译以及无中间件依赖方式

一、拉取源码以及前期准备

源码地址
  1. github:https://github.com/opengoofy/hippo4j
  2. gitee:https://gitee.com/opengoofy/hippo4j
目录结构

directory.png

数据库录入(MySQL)
  1. 在 "/hippo4j-develop/hippo4j-server/hippo4j-bootstrap/conf" 目录下找到“hippo4j_manager.sql”并导入,导入后如图
    sqlconfig.png

二、服务端启动

配置更改
  1. 在" /hippo4j-develop/hippo4j-server/hippo4j-bootstrap/src/main/resources "下找到 “application.properties”文件,更改数据库用户名以及密码

    1spring.datasource.username=root
    2spring.datasource.password=root
    
  2. 找到启动类后启动,位置:“/hippo4j-develop/hippo4j-server/hippo4j-bootstrap/src/main/java/cn/hippo4j/server/ServerApplication.java”

  3. 启动成功后网页打开"http://localhost:6691/index.html",默认用户名、密码 admin 123456,启动后如图

    index.png

三、客户端启动

示例项目启动
  1. 启动“/hippo4j-develop/hippo4j-example/hippo4j-spring-boot-starter-example/src/main/java/cn/hippo4j/example/server/ServerExampleApplication.java”应用类;

  2. 默认项目已经帮你创建好了示例项目的租户、项目、线程池;

    1. Hippo4j 按照租户、项目、线程池的维度划分。举个例子,小编在一家公司的公共组件团队,团队中负责消息、短链接网关等项目。公共组件是租户,消息或短链接就是项目。
  3. 动态更新线程池参数:

    1. 动态线程池 — 线程池实例 — 选择对应的租户、项目以及线程池实例
      Snipaste20230413145645.png
    2. 编辑此线程池实例,可以修改各种参数,项目控制台输出更新日志及代表成功
      Snipaste20230413150916.png
实际项目使用(SpringBoot)
  1. pom 文件引入对应依赖

    1        <dependency>
    2            <groupId>cn.hippo4j</groupId>
    3            <artifactId>hippo4j-spring-boot-starter</artifactId>
    4            <version>1.4.3-upgrade</version>
    5        </dependency>
    
  2. 启动类加注解

    1@SpringBootApplication
    2@EnableDynamicThreadPool
    3public class DemoApplication {
    4    public static void main(String[] args) {
    5        SpringApplication.run(DemoApplication.class, args);
    6    }
    7}
    
  3. 线程池改造

     1package com.demo.config;
     2
     3import cn.hippo4j.core.executor.DynamicThreadPool;
     4import cn.hippo4j.core.executor.support.ThreadPoolBuilder;
     5import org.springframework.context.annotation.Bean;
     6import org.springframework.context.annotation.Configuration;
     7
     8import java.util.concurrent.ThreadPoolExecutor;
     9
    10@Configuration
    11public class ThreadPoolConfig {
    12
    13    @Bean
    14    @DynamicThreadPool
    15    public ThreadPoolExecutor messageConsumeDynamicExecutor() {
    16        String threadPoolId = "message-consume-demo";
    17        return ThreadPoolBuilder.builder()
    18                .threadFactory(threadPoolId)
    19                .threadPoolId(threadPoolId)
    20                .dynamicPool()
    21                .build();
    22    }
    23
    24}
    
  4. 配置文件(yaml)

     1spring:
     2  profiles:
     3    active: dev
     4  application:
     5    # 服务端创建的项目 id 需要与 application.name 保持一致
     6    name: study-service
     7  dynamic:
     8    thread-pool:
     9      # 服务端地址
    10      server-addr: http://localhost:6691
    11      # 用户名
    12      username: admin
    13      # 密码
    14      password: 123456
    15      # 租户 id, 对应 tenant 表
    16      namespace: demo
    17      # 项目 id, 对应 item 表
    18      item-id: study-service
    
  5. 服务端配置租户、项目以及线程池管理

    1. 租户可以使用已存在的,建议新建一个租户;
      Snipaste20230413152851.png
    2. 创建项目,选择租户,项目一栏需填写客户端的 application.name
      Snipaste20230413153048.png
    3. 动态线程池中创建线程池管理,选择租户、项目,线程池一栏填入客户端创建的线程池 threadpoolId
      Snipaste20230413153249.png
  6. 客户端项目启动

    1. 创建完成,启动客户端项目,启动日志输出
      Snipaste20230413153750.png

    2. 启动成功,查看服务端日志输出

      12023-04-13 15:39:11.192  INFO 20992 --- [er.long.polling] c.h.config.service.LongPollingService    : Dynamic Thread Pool Long pulling client count: 2
      

      这里的 count 代表客户端实例为两个,一个是示例项目,一个是实际项目

  7. 查看服务端网页,动态线程池 — 线程池实例,选择租户、项目、线程池后查询

    Snipaste20230413154253.png

  8. 至此已经监控到客户端的线程池实例,可在此页面动态更改线程池参数,线程池管理和线程池实例的区别

    1. 在线程池管理中修改线程池参数,客户端并不能实时感知并变更参数,需要重启客户端。而线程池实例中去对具体的实例修改参数时,客户端无需重启,可以试试感知到参数变化。如果二者针对同一线程池的参数配置不同,则在重启客户端时,客户端会去拉取线程池管理中的参数配置;
    2. 二者对应的定位:线程池管理中的配置是常态化配置,而线程池实例中的配置变成更像是一种临时修改,比如突发的流量激增等场景,并不具备普适性。
异常告警(企业微信)
  1. 先找个企微群,企业微信创建机器人,机器人创建教程(https://open.work.weixin.qq.com/help2/pc/14931?person_id=1&from=homesearch);
  2. 机器人加入至群聊后,取机器人 Webhook 地址中的 key 值,图中红圈圈起来的马赛克部分,以及机器人的名字,创建机器人的时候会输入;
    Snipaste20230413160152.png
  3. 服务端异常告警通知配置
    Snipaste20230413155513.png
  4. 测试编辑线程池实例参数通知
    Snipaste20230413155654.png
  5. 测试动态线程池异常通知
    Snipaste20230413155747.png
  6. 其余平台通知请自行尝试,按照官网文档说明;

标题:Hippo4j动态线程池监控接入
作者:zzzzchen
地址:https://www.dczzs.com/articles/2023/04/12/1681288036887.html