View Code? Open in Web Editor
NEW
📌 异步线程池框架,支持线程池动态变更&监控&报警,无需修改代码轻松引入。Asynchronous thread pool framework, support Thread Pool Dynamic Change & monitoring & Alarm, no need to modify the code easily introduced.
Home Page: https://hippo4j.cn
License: Apache License 2.0
Java 77.01%
HTML 0.23%
CSS 0.02%
Shell 0.13%
Batchfile 0.05%
Dockerfile 0.05%
JavaScript 3.13%
Vue 16.31%
SCSS 0.60%
TypeScript 2.43%
Less 0.05%
hippo4j's People
hippo4j's Issues
问题原因
对项目的基础表名进行了修改,如下:
config_info -> config
item_info -> item
tenant_info -> tenant
解决方案
执行 初始化 SQL 脚本 重新导入
当客户端集群部署多个实例时,针对单实例修改线程池配置,不会影响其它实例配置
Hippo4J 服务端请求默认需要鉴权,新增鉴权开关功能
Hippo4J 内部 OkHttp 超时调用 API 依赖版本过高,尽量降低依赖或换一种超时实现方式
call .timeout ().timeout (readTimeoutMs , TimeUnit .MILLISECONDS );
业务背景:hippo4j starter 在启动时通过 spring 后置处理器,处理动态线程池配置拉取以及配置订阅;为了优化启动速度,采用线程池执行
代码位置:cn.hippo4j.starter.core.DynamicThreadPoolPostProcessor
private final ExecutorService executorService = ThreadPoolBuilder .builder ()
.poolThreadSize (2 , 4 )
.keepAliveTime (0L , TimeUnit .MILLISECONDS )
.workQueue (QueueTypeEnum .ARRAY_BLOCKING_QUEUE , 1 )
.threadFactory ("dynamic-threadPool-config" )
.rejected (new ThreadPoolExecutor .DiscardOldestPolicy ())
.build ();
优化方案:设置线程池内线程,在指定时间无执行动作后销毁
如果更新代码运行出错,大概率是因为项目新增或修改了表结构
目前还在开发阶段,所以没有增量脚本,用户直接使用初始化脚本覆盖即可
初始化 SQL 脚本地址:hippo4j_manager.sql
Starter 在和服务端交互的过程中需要携带上用户名密码,目前是通过服务端放开指定路径拦截
目前我设想数据采集监控指标分两部分:线程池任务执行时间
和 线程池运行时的状态
线程池运行时的状态
当前线程
最大线程
队列容量
队列元素数量
任务总量
拒绝策略执行次数
论点:需要采集上报哪些数据?采集的时间和上报的时间如何定义?
问题:服务端更新一个不存在的实例,会将不存在的实例添加至实例列表中
解决方案:当修改服务实例不存在时,通过抛异常的方式终止请求
线程池历史运行数据默认保持 30 分钟(可定制),这个也是监控中能够看到的指标数据
因为默认是 MySQL 存储,所以需要定时删除
大佬们好,
此 Issue 会展示动态线程池(Dynamic-ThreadPool)相关的使用介绍、上线生产文章,并且后续会逐步完善动态线程池项目的相关建设,敬请期待 😊。
如果您有好的意见,也欢迎评论反馈!
公司私服nexus禁用了fastjson,所以只能用gson或者jackson
希望在线程池实例页面,可以查看到线程池内线程相关运行堆栈信息
如果可行的话
这里使用延时队列去上报数据,是否会对系统造成性能上的损耗
Error message :
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.835 s
[INFO] Finished at: 2021-12-03T14:46:32+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-gpg-plugin:1.6:sign (default) on project hippo4j-all: Unable to execute gpg command: Error while executing process. Cannot run program "gpg": error=2, No such file or directory -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
zhaojinchao@zhaojinchao的MacBook dynamic-threadpool %
获取不到服务端配置和实例时,会抛出空指针异常,对排查问题并不友好,所以需要抛出更明显的异常的信息
谁在使用 Hippo4j
非常感谢社区朋友对 Hippo4j 的关注和支持,我们会持续投入精力开发和维护,支持 Hippo4j 走的更远。
生产环境已接入的公司,欢迎在该 Issue 登记,登记仅仅为了产品推广。
此 Issue 的目的
收集在生产上使用 Hippo4j 的用户
聆听社区内一线开发声音,让 Hippo4j 变得更好
吸引更多的人参与贡献,扩大社区和个人影响力
更多的了解 Hippo4j 的实际使用场景,以方便下一步的规划
登记使用情况的好处
专家服务(积极响应,优先支持,落地方案和场景讨论),帮助大家更高效的落地 Hippo4j
个人影响力构建,Committer 候选人 (登记用户可以获得 1:1 Hippo4j Committer 培养的支持)
期待您能提供
示例格式:
地点:北京
组织:xxx 公司
官网:xxxxx.com
另外,可以在官网 采用公司 页面提交 PR,加上 Issue 评论的所在公司。
开始行动,使用 Hippo4j
如果您还对 Hippo4j 的开发和生产上线有问题,欢迎添加微信好友(备注:hippo4j)与我进行联系,邀您入沟通群。
目前从客户端收集而来的线程池历史运行数据,默认存储一小时,需要将此时间支持配置文件自定义
目前线程池监控中只展示线程池已执行任务的总数,意义不是很大,希望能加个某个时间段内的任务处理数统计
通过 @DynamicThreadPool
注解创建动态线程池使用到通过 springBeanName 获取方法上标记的注解
ListableBeanFactory#findAnnotationOnBean(java.lang.String, java.lang.Class)
该方法在 SpringBoot version 2.2.0.RELEASE 之前使用有点鸡肋,也就获取不到对应的注解
为了适配低版本 SpringBoot,特开发 DynamicThreadPoolAnnotationUtil#findAnnotationOnBean(java.lang.String, java.lang.Class)
具体描述,详情查看类注释
具体上下文调用逻辑查看 cn.hippo4j.starter.core.DynamicThreadPoolPostProcessor#postProcessAfterInitialization
请教一下 server 端 ConfigChangePublisher.notifyConfigChange(new LocalDataChangeEvent(identify, ContentUtil.getGroupKey(configInfo))); 发布了事件,client 怎么获取到事件。
这是2个系统,如果实现交互
client 的 cn.hippo4j.starter.core.ThreadPoolDynamicRefresh#refreshDynamicPool(java.lang.String) 调用的上层是哪里?
创建、修改线程池参数时,支持自定义线程池拒绝策略
使用者反馈:部署 1.0.0-alpha 版本到公司环境,/hippo4j/v1/cs/configs/listener
会重复请求导致连接超时
因为无法复现问题,所以只能以解决问题优先
为什么要将报警通知抽离为单独的模块
hippo4j 不可能将所有的发送平台全部集成,需要支持 SPI 设计让使用者自定义
目录设计与 starter 组件有所冲突。最初为了设计的简洁,报警通知所有类都在一个包下
目前报警通知目录地址:Alarm
当客户端有多个线程池实例时,比如 dynamic-threadpool-1
、dynamic-threadpool-2
因为项目启动加载时机问题,初始化向服务端注册时,仅会带上其中一个实例,大概 30 秒后其它实例才会跟随轮询请求注册上去
按照文档来的 启动连接 server端发现心跳会抱异常 HttpScheduledHealthCheck
加入 钉钉群:31764717
导入 Hippo 初始化 SQL 语句
启动 dynamic-threadpool-server 模块下 ServerApplication 应用类
启动 dynamic-threadpool-example 模块下 ExampleApplication 应用类
HTTP Post 调用 http://localhost:6691/v1/cs/configs ,Body 请求体如下:
{
"ignore" : " tenantId、itemId、tpId 代表唯一线程池,请不要修改" ,
"tenantId" : " prescription" ,
"itemId" : " dynamic-threadpool-example" ,
"tpId" : " message-produce" ,
"coreSize" : 10 ,
"maxSize" : 15 ,
"queueType" : 9 ,
"capacity" : 100 ,
"keepAliveTime" : 10 ,
"rejectedType" : 3 ,
"isAlarm" : 0 ,
"capacityAlarm" : 80 ,
"livenessAlarm" : 80
}
以下代码可能会导致监听 spring 刷新事件无法执行
@ Override
public void onApplicationEvent (ContextRefreshedEvent event ) {
synchronized (ServerHealthCheck .class ) {
if (event .getApplicationContext ().getParent () == null ) {
contextInitComplete = true ;
}
}
}
全局控制 ContextRefreshedEvent 事件只执行一次即可
The method selectPage(E, Wrapper) in the type BaseMapper is not applicable for the arguments (ItemQueryReqDTO, LambdaQueryWrapper)
设置不启用动态线程池功能时,取消下方字段的必填校验
/**
* Username.
*/
private String username ;
/**
* Password.
*/
private String password ;
/**
* Server addr
*/
private String serverAddr ;
/**
* Namespace
*/
private String namespace ;
/**
* Item id
*/
private String itemId ;
描述:客户端启动后,修改其中一个动态线程池的参数,其它线程池也会跟着一起修改
问题原因:因为获取服务端线程池配置时都是通过实例表获取,条件传递不足导致查询错误
作者你好,我试用了一下工程发现微服务下多个节点的配置不能差异化,只要一个节点的配置修改,其他节点的配置也会相应改变,后期有规划把配置细化到服务下的不同实例吗
如果在 springcloud 环境下,因为存在 org.springframework.cloud.client.discovery.DiscoveryClient 导致在装配 cn.hippo4j.starter.core.DiscoveryClient 时出现冲突,需要修改为或设置 Bean.value 属性
@ Bean
public DiscoveryClient customDiscoveryClient (HttpAgent httpAgent , InstanceInfo instanceInfo ) {
return new DiscoveryClient (httpAgent , instanceInfo );
}
/**
* 发生拒绝事件时, 添加新任务并运行最早的任务
*/
public static class RunsOldestTaskPolicy implements RejectedExecutionHandler {
@ Override
public void rejectedExecution (Runnable r , ThreadPoolExecutor executor ) {
if (executor .isShutdown ()) {
return ;
}
BlockingQueue <Runnable > workQueue = executor .getQueue ();
Runnable firstWork = workQueue .poll ();
boolean newTaskAdd = workQueue .offer (r );
if (firstWork != null ) {
firstWork .run ();
}
if (!newTaskAdd ) {
executor .execute (r );
}
}
}
/**
* 使用阻塞方法将拒绝任务添加队列, 可保证任务不丢失
*/
public static class SyncPutQueuePolicy implements RejectedExecutionHandler {
@ Override
public void rejectedExecution (Runnable r , ThreadPoolExecutor executor ) {
if (executor .isShutdown ()) {
return ;
}
try {
executor .getQueue ().put (r );
} catch (InterruptedException e ) {
log .error ("Adding Queue task to thread pool failed." , e );
}
}
}
目前 Hippo4J 对于报警通知的配置是客户端项目启动的时候拉取一次,客户端运行时,服务端修改报警通知配置不会动态变更客户端。除非服务端修改后,客户端重启
现在是否有必要将这块报警通知配置作为动态更新?
根据现有流程,如果客户端进行关闭时会将服务端线程池实例一同销毁
但是,如果客户端被 kill -9 强制关闭,则不会执行销毁服务端线程池实例
服务端和客户端在进行交互时,将 + 作为分割字符,需要过滤租户、项目、线程池的新增修改功能,存在敏感数据抛异常