Hippo4j动态线程池监控接入
简单了解
线程池痛点
原文摘录
线程池是一张基于池化思想管理线程的工具,使用线程池可以减少创建销毁线程的开销,避免线程过多导致系统资源耗尽。在高并发以及大批量的任务处理场景,线程池的使用是必不可少的。
如果有在项目中实际使用线程池,相信你可能会遇到一下痛点
- 线程池随便定义,线程资源过多,造成服务器高负载;
- 线程池参数不易评估,随着业务的并发提升,业务面临出现故障的风险;
- 线程池任务执行时间超过平均时间,开发人员无法感知;
- 线程池任务堆积,触发拒绝策略,影响既有业务正常运行;
- 当业务出现超时、熔断等问题时,因为没有监控,无法确定是不是线程池引起;
- 原生线程池不支持运行时变量的传递,比如 MDC 上下文遇到线程池就 GC。
- 无法执行优雅关闭,当项目关闭时,大量正在运行的线程池任务被丢弃;
- 线程池运行中,任务执行停止,怀疑发生死锁或执行耗时操作,但是无从下手;
如果同学们有以上的问题或者疑问,接着往下看。
什么是 Hippo4j
原文摘录
Hippo4j 通过对 JDK 线程池增强,以及扩展三方框架底层线程池等功能,为业务系统提高线上运行保障能力。
提供一下功能支持
- 全局管控 - 管理应用线程池实例;
- 动态变更 - 应用运行时动态变成线程池参数,包括不限于:核心、最大线程数、阻塞队列容量、拒绝策略等。
- 通知报警 - 内置四种报警通知策略,线程池活跃度、容量水位、拒绝策略以及任务执行时间超长;
- 运行监控 - 实时查看线程池运行时数据,最近半小时线程池运行数据图表展示;
- 功能扩展 - 支持线程池任务传递上下文,项目关闭时,支持等待线程池在指定时间内完成任务;
- 多种模式 - 内置两种使用模式:依赖配置中心 和 无中间件依赖。
- 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更;
- 框架适配 - Dubbo、Hystrix、RabbitMQ、RocketMQ 等消费线程池运行时数据查看和线程数变更。
正文
采用源码编译以及无中间件依赖方式
一、拉取源码以及前期准备
源码地址
目录结构
数据库录入(MySQL)
- 在 "/hippo4j-develop/hippo4j-server/hippo4j-bootstrap/conf" 目录下找到“hippo4j_manager.sql”并导入,导入后如图
二、服务端启动
配置更改
-
在" /hippo4j-develop/hippo4j-server/hippo4j-bootstrap/src/main/resources "下找到 “application.properties”文件,更改数据库用户名以及密码
1spring.datasource.username=root 2spring.datasource.password=root
-
找到启动类后启动,位置:“/hippo4j-develop/hippo4j-server/hippo4j-bootstrap/src/main/java/cn/hippo4j/server/ServerApplication.java”
-
启动成功后网页打开"
http://localhost:6691/index.html
",默认用户名、密码 admin 123456,启动后如图
三、客户端启动
示例项目启动
-
启动“/hippo4j-develop/hippo4j-example/hippo4j-spring-boot-starter-example/src/main/java/cn/hippo4j/example/server/ServerExampleApplication.java”应用类;
-
默认项目已经帮你创建好了示例项目的租户、项目、线程池;
- Hippo4j 按照租户、项目、线程池的维度划分。举个例子,小编在一家公司的公共组件团队,团队中负责消息、短链接网关等项目。公共组件是租户,消息或短链接就是项目。
-
动态更新线程池参数:
- 动态线程池 — 线程池实例 — 选择对应的租户、项目以及线程池实例
- 编辑此线程池实例,可以修改各种参数,项目控制台输出更新日志及代表成功
- 动态线程池 — 线程池实例 — 选择对应的租户、项目以及线程池实例
实际项目使用(SpringBoot)
-
pom 文件引入对应依赖
1 <dependency> 2 <groupId>cn.hippo4j</groupId> 3 <artifactId>hippo4j-spring-boot-starter</artifactId> 4 <version>1.4.3-upgrade</version> 5 </dependency>
-
启动类加注解
1@SpringBootApplication 2@EnableDynamicThreadPool 3public class DemoApplication { 4 public static void main(String[] args) { 5 SpringApplication.run(DemoApplication.class, args); 6 } 7}
-
线程池改造
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}
-
配置文件(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
-
服务端配置租户、项目以及线程池管理
- 租户可以使用已存在的,建议新建一个租户;
- 创建项目,选择租户,项目一栏需填写客户端的 application.name
- 动态线程池中创建线程池管理,选择租户、项目,线程池一栏填入客户端创建的线程池 threadpoolId
- 租户可以使用已存在的,建议新建一个租户;
-
客户端项目启动
-
创建完成,启动客户端项目,启动日志输出
-
启动成功,查看服务端日志输出
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 代表客户端实例为两个,一个是示例项目,一个是实际项目
-
-
查看服务端网页,动态线程池 — 线程池实例,选择租户、项目、线程池后查询
-
至此已经监控到客户端的线程池实例,可在此页面动态更改线程池参数,线程池管理和线程池实例的区别
- 在线程池管理中修改线程池参数,客户端并不能实时感知并变更参数,需要重启客户端。而线程池实例中去对具体的实例修改参数时,客户端无需重启,可以试试感知到参数变化。如果二者针对同一线程池的参数配置不同,则在重启客户端时,客户端会去拉取线程池管理中的参数配置;
- 二者对应的定位:线程池管理中的配置是常态化配置,而线程池实例中的配置变成更像是一种临时修改,比如突发的流量激增等场景,并不具备普适性。
异常告警(企业微信)
- 先找个企微群,企业微信创建机器人,机器人创建教程(https://open.work.weixin.qq.com/help2/pc/14931?person_id=1&from=homesearch);
- 机器人加入至群聊后,取机器人 Webhook 地址中的 key 值,图中红圈圈起来的马赛克部分,以及机器人的名字,创建机器人的时候会输入;
- 服务端异常告警通知配置
- 测试编辑线程池实例参数通知
- 测试动态线程池异常通知
- 其余平台通知请自行尝试,按照官网文档说明;