首页 文章详情

给你介绍下,Hippo4J 动态线程池基础架构

源码兴趣圈 | 278 2021-11-07 23:14 0 0 0
UniSMS (合一短信)

很多小伙伴知道小编从今年六月份开始,陆陆续续开始提交 Hippo4J 动态线程池项目

经过 200+ 的 Commit,也是快要能发布 1.0.0 正式版本,今天就写一篇文章正式介绍下 Hippo4J 的项目架构

Hippo4J GitHub[1]:https://github.com/acmenlt/dynamic-threadpool

小伙伴如果访问 GitHub 速度慢,可以通过改 Host 的方式提高访问速度,修改 Host 方案[2]

1. 架构设计

简单来说,Hippo4J 从部署的角度上分为两种角色:Server 端和 Client 端

Server 端是 Hippo4J 项目打包出的 Java 进程,功能包括用户权限、线程池监控以及执行持久化的动作

Client 端指的是我们 SpringBoot 应用,通过引入 Hippo4J Starter Jar 包负责与 Server 端进行交互

比如拉取 Server 端线程池数据、动态更新线程池配置以及采集上报线程池运行时数据等

2. 基础组件

2.1 配置中心(Config)

配置中心位于 Server 端,它的主要作用是监控 Server 端线程池配置变更,实时通知到 Client 实例执行线程池变更流程

代码设计基于 Nacos 1.x 版本的 长轮询以及异步 Servlet 机制 实现

2.2 注册中心(Discovery)

负责管理 Client 端(单机或集群)注册到 Server 端的实例,包括不限于实例注册、续约、过期剔除 等操作,代码基于 Eureka 源码实现

上面的配置中心很容易理解,动态线程池参数变更的根本。但是注册中心是用来做什么的?

注册中心管理 Client 端注册的实例,通过这些实例可以 实时获取线程池的运行时参数信息

目前的设计是如此,不排除后续基于 Discovery 做更多的扩展

2.3 控制台(Console)

对接前端项目,包括不限于以下模块管理

2.4 抽象工具(Tools)

顾名思义就是将某些工具单独抽象出来,并以 Module 的形式进行展现,这样的拆分方式有两点好处:一是更符合职责分离特性,二是需要用到某块功能,做到拿来即用

目前已集成两块内容:

  1. log-record-tool:基于 mzt-biz-log[3] 的操作日志变更记录组件
  2. open-change-tool:监控 Hippo4J 项目在 GitHub 的 Star Fork 变更,默认五分钟内有变更则通知

3. 消息通知(Notify)

Hippo4J 内置了很多需要通知的事件,比如:线程池参数变更通知、线程池活跃度报警、拒绝策略执行报警以及阻塞队列容量报警等

目前 Notify 已经接入了钉钉,后续持续集成企业微信、邮件、短信等通知渠道;并且,Notify 模块提供了消息事件的 SPI 方案,可以接受三方自定义的推送

4. Hippo4j-Spring-Boot-Starter

熟悉 SpringBoot 的小伙伴对 Starter 应该不会陌生。Hippo4J 提供以 Starter Jar 包的形式嵌套在应用内,负责与 Server 端完成交互

Starter Jar 包推送到 Maven 公共仓库,目前公共仓库已存在 0.0.2 版本的 Jar

5. SpringBoot 快速开始

5.1 Server 端启动

导入 Hippo4J 初始化 SQL 语句[4]

Hippo4J[5] 代码拉至本地,启动 Server[6] 模块下 ServerApplication 应用类

5.2 SpringBoot 引入 Hippo4j Starter

SpringBoot 应用引入 Hippo4j Starter Jar。备注:0.0.2 版本仅是过渡期版本,正式请等待发布 1.0.0

<dependency>
    <groupId>io.github.acmenlt</groupId>
    <artifactId>hippo4j-spring-boot-starter</artifactId>
    <version>0.0.2</version>
</dependency>

SpringBoot 应用添加 Hippo4J 相关配置文件:

spring:
  profiles:
    active: dev
  application:
    name: dynamic-threadpool-example
  dynamic:
    thread-pool:
      notifys:
        - type: DING
          url: https://oapi.dingtalk.com/robot/send?access_token=
          # 此处可以选择自己的钉钉群
          token: 4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae
          # 通知时 @ 人员
          receives: '15601166691'
      # 报警发送间隔
      alarm-interval: 30
      # 服务端地址
      server-addr: http://localhost:6691
      # 租户 id, 对应 tenant 表
      namespace: prescription
      # 项目 id, 对应 item 表
      item-id: ${spring.application.name}

添加线程池配置类,动态线程池支持两种创建方式

  1. DynamicThreadPoolWrapper 包装器创建,指定线程池标识
  2. @DynamicThreadPool 注解修饰 Spring Bean

Spring 后置处理器会扫描这两种方式创建的 Bean,拿到线程池 ID 调用 Server 端获取配置

如果获取 Server 端配置失败,根据默认线程池创建实例

@Configuration
public class ThreadPoolConfig {
    public static final String MESSAGE_PRODUCE = "message-produce";
    public static final String MESSAGE_CONSUME = "message-consume";

    @Bean
    // {@link DynamicThreadPoolWrapper} 完成 Server 端订阅配置功能.
    public DynamicThreadPoolWrapper messageCenterDynamicThreadPool() {
        return new DynamicThreadPoolWrapper(MESSAGE_CONSUME);
    }

    @Bean
    @DynamicThreadPool
    // 通过 {@link DynamicThreadPool} 修饰 {@link DynamicThreadPoolExecutor} 完成 Server 端订阅配置功能.
    // 由动态线程池注解修饰后, IOC 容器中保存的是 {@link DynamicThreadPoolExecutor}
    public ThreadPoolExecutor dynamicThreadPoolExecutor() {
        return ThreadPoolBuilder.builder().threadFactory(MESSAGE_PRODUCE).dynamicPool().build();
    }
}

启动 SpringBoot 应用后,动态线程池的准备工作就算完成了

5.3 测试线程池动态变更

通过接口修改线程池中的配置。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"81,
    "livenessAlarm"82
}

接口调用成功后,观察 IDEA Client 控制台日志输出,日志输出包括不限于此信息即为成功

[🔥 MESSAGE-PRODUCE] Changed thread pool. coreSize :: [11=>10], maxSize :: [15=>15], queueType :: [9=>9], capacity :: [100=>100], keepAliveTime :: [10000=>10000], rejectedType :: [7=>7]

另外,当 Client 集群部署时,可以选择修改所有实例或某一实例。修改请求路径:http://localhost:6691/v1/cs/configs?identify=xxx ,Body 体同上

identify 参数如何获取?每一台 Client 端都会分配到独一无二的值,并在启动时进行打印

Client identity :: xxxxxx

identify 参数不传或为空,会修改该线程池 Client 集群下该线程池所有实例参数

5.4 报警通知

如果加入了钉钉群(号码:31764717)的小伙伴,此时就能收到一条钉钉机器人的推送通知,示例如下:

       
         

7. 最后

在 GitHub 上,检验项目的质量如何,Star 数占了一定因素;从上次 Hippo4J 登上 GitHub Trending 至今,已收获 400+ Star 数,进而证明了 Hippo4J 的项目质量

随着时间的推移,更多的小伙伴关注到 Hippo4J 项目,提出了相关的功能建议,以及希望参与项目共建,整体显得朝气蓬勃

下图来自小伙伴的问题以及建议,提的内容都非常好 👍👍👍

如果说看了上面的介绍,让你对 Hippo4J 产生了兴趣,通过以下方式联系到小编,不仅可以解答你对 Hippo4J 项目的疑惑,同时也接受正向的功能建议

一直以来,Hippo4J 目标一直都是企业级应用,小编也不断在向这个方向对齐,发布 1.0 的时间不会太远

屏幕前的小伙伴,如果觉得项目功能规划、代码设计还不错的话,辛苦点个 🚀 Star ,方便后续查看

对于这个项目,是否有什么不一样看法,欢迎在评论区一起沟通交流~

参考

[1]

Hippo4J GitHub: https://github.com/acmenlt/dynamic-threadpool

[2]

修改 Host 方案: https://gitee.com/isevenluo/github-hosts

[3]

mzt-biz-log: https://github.com/mouzt/mzt-biz-log

[4]

Hippo4J 初始化 SQL 语句: https://sourl.cn/yQ5dNB

[5]

Hippo4J: https://github.com/acmenlt/dynamic-threadpool

[6]

Server: https://github.com/acmenlt/dynamic-threadpool/tree/develop/server


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter