Merge branch 'opengoofy:develop' into develop

pull/883/head
黄成兴 3 years ago committed by GitHub
commit ea729ad2cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

2
.gitignore vendored

@ -39,4 +39,4 @@ build/
### Docs ### ### Docs ###
docs/node_modules docs/node_modules
docs/build docs/build
docs/.docusaurus docs/.docusaurus

@ -0,0 +1,56 @@
<img align="center" width="400" alt="image" src="https://user-images.githubusercontent.com/77398366/181906454-b46f6a14-7c2c-4b8f-8b0a-40432521bed8.png">
# Dynamic and observable thread pool framework
[![Gitee](https://gitee.com/itmachen/hippo4j/badge/star.svg?theme=gvp)](https://gitee.com/itmachen/hippo4j) [![GitHub](https://img.shields.io/github/stars/opengoofy/hippo4j)](https://github.com/opengoofy/hippo4j) [![Docker Pulls](https://img.shields.io/docker/pulls/hippo4j/hippo4j-server.svg)](https://store.docker.com/community/images/hippo4j/hippo4j-server) [![Contributors](https://img.shields.io/github/contributors/opengoofy/hippo4j?color=3ba272)](https://github.com/opengoofy/hippo4j/graphs/contributors) [![License](https://img.shields.io/github/license/opengoofy/hippo4j?color=5470c6)](https://github.com/opengoofy/hippo4j/blob/develop/LICENSE)
-------
## Thread pool pain points
A thread pool is a tool for managing threads based on the idea of pooling.
Using a thread pool reduces the overhead of creating and destroying threads and avoids running out of system resources due to too many threads.
The use of thread pools is essential in highly concurrent and high-volume task processing scenarios.
If you have actually used thread pools in your projects, I believe you may have encountered the following pain points:
- Thread pools are defined randomly, with too many thread resources, causing high server load.
- The thread pool parameters are not easily evaluated and the business is at risk of failure.
- Thread pool task execution time exceeds the average execution cycle and developers are not informed.
- Thread pool tasks pile up and affect business operations.
- Wireless process pool monitoring when the service has timeouts, meltdowns, and other problems.
- Thread pools do not support the passing of runtime variables, such as MDC contexts.
- When a project is closed, a large number of running thread pool tasks are discarded.
- Thread pool running, task execution stopped, don't know the problem.
## What is Hippo-4J
Hippo-4J through the JDK thread pool enhancements, as well as extending the three-party framework underlying thread pools and other features for business systems to improve online operational security capabilities.
The following functional support is provided:
- Global Control - Managing Application Thread Pool Instances.
- Dynamic changes - dynamically changing thread pool parameters at application runtime.
- Notify alarms - Four built-in alarm notification policies.
- Run Monitoring - Real-time view of thread pool runtime data.
- Feature extensions - support for thread pooling task passing contexts, etc.
- Multiple Modes - Two built-in usage modes: Configuration Center Mode and No Middleware Mode.
- Container Management - Tomcat, Jetty, Undertow container thread pool runtime view and thread count changes.
- Framework adaptation - Dubbo, Hystrix, Polaris, RabbitMQ, RocketMQ and other consumer thread pool runtime data view and thread count changes.
## Quick Start
For local presentation purposes, see [Quick start](https://hippo4j.cn/docs/user_docs/user_guide/quick-start).
Demo Environment: [http://console.hippo4j.cn/index.html](http://console.hippo4j.cn/index.html).
## Who is using
More companies with access are welcome to register at [registration address](https://github.com/opengoofy/hippo4j/issues/13), registration is only for product promotion.
## Contributors
Thanks to all the developers who contributed to the project. If interested in contributing, refer to [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).

@ -1,5 +1,7 @@
<img align="center" width="400" alt="image" src="https://user-images.githubusercontent.com/77398366/181906454-b46f6a14-7c2c-4b8f-8b0a-40432521bed8.png"> <img align="center" width="400" alt="image" src="https://user-images.githubusercontent.com/77398366/181906454-b46f6a14-7c2c-4b8f-8b0a-40432521bed8.png">
中文 | [English](https://github.com/opengoofy/hippo4j/blob/develop/README-EN.md)
# 动态可观测线程池框架,提高线上运行保障能力 # 动态可观测线程池框架,提高线上运行保障能力
[![Gitee](https://gitee.com/itmachen/hippo4j/badge/star.svg?theme=gvp)](https://gitee.com/itmachen/hippo4j) [![GitHub](https://img.shields.io/github/stars/opengoofy/hippo4j)](https://github.com/opengoofy/hippo4j) [![Docker Pulls](https://img.shields.io/docker/pulls/hippo4j/hippo4j-server.svg)](https://store.docker.com/community/images/hippo4j/hippo4j-server) [![Contributors](https://img.shields.io/github/contributors/opengoofy/hippo4j?color=3ba272)](https://github.com/opengoofy/hippo4j/graphs/contributors) [![License](https://img.shields.io/github/license/opengoofy/hippo4j?color=5470c6)](https://github.com/opengoofy/hippo4j/blob/develop/LICENSE) [![Gitee](https://gitee.com/itmachen/hippo4j/badge/star.svg?theme=gvp)](https://gitee.com/itmachen/hippo4j) [![GitHub](https://img.shields.io/github/stars/opengoofy/hippo4j)](https://github.com/opengoofy/hippo4j) [![Docker Pulls](https://img.shields.io/docker/pulls/hippo4j/hippo4j-server.svg)](https://store.docker.com/community/images/hippo4j/hippo4j-server) [![Contributors](https://img.shields.io/github/contributors/opengoofy/hippo4j?color=3ba272)](https://github.com/opengoofy/hippo4j/graphs/contributors) [![License](https://img.shields.io/github/license/opengoofy/hippo4j?color=5470c6)](https://github.com/opengoofy/hippo4j/blob/develop/LICENSE)
@ -36,7 +38,7 @@ Hippo-4J 通过对 JDK 线程池增强,以及扩展三方框架底层线程池
- 功能扩展 - 支持线程池任务传递上下文;项目关闭时,支持等待线程池在指定时间内完成任务。 - 功能扩展 - 支持线程池任务传递上下文;项目关闭时,支持等待线程池在指定时间内完成任务。
- 多种模式 - 内置两种使用模式:[依赖配置中心](https://hippo4j.cn/docs/user_docs/getting_started/config/hippo4j-config-start) 和 [无中间件依赖](https://hippo4j.cn/docs/user_docs/getting_started/server/hippo4j-server-start)。 - 多种模式 - 内置两种使用模式:[依赖配置中心](https://hippo4j.cn/docs/user_docs/getting_started/config/hippo4j-config-start) 和 [无中间件依赖](https://hippo4j.cn/docs/user_docs/getting_started/server/hippo4j-server-start)。
- 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更。 - 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更。
- 中间件适配 - Dubbo、Hystrix、Polaris、RabbitMQ、RocketMQ 等消费线程池运行时数据查看和线程数变更。 - 框架适配 - Dubbo、Hystrix、RabbitMQ、RocketMQ 等消费线程池运行时数据查看和线程数变更。
## 快速开始 ## 快速开始

@ -52,6 +52,6 @@ cn.hippo4j.example.core.handler.ErrorLogRejectedExecutionHandler
2022-08-01 21:27:49.515 ERROR 48928 --- [ateHandler.test] r$CustomErrorLogRejectedExecutionHandler : 线程池抛出拒绝策略 2022-08-01 21:27:49.515 ERROR 48928 --- [ateHandler.test] r$CustomErrorLogRejectedExecutionHandler : 线程池抛出拒绝策略
``` ```
:::tip :::note
具体参考 `hippo4j-example/hippo4j-spring-boot-starter-example` 模块。 具体参考 `hippo4j-example/hippo4j-spring-boot-starter-example` 模块。
::: :::

@ -10,7 +10,7 @@ sidebar_position: 3
需要注意,项目 ID 需要与配置文件 `{application.name}` 保持一致。 需要注意,项目 ID 需要与配置文件 `{application.name}` 保持一致。
:::tip :::note
租户、项目、线程池 ID 如果由多个词组成,建议以 - 进行分割。比如message-center。 租户、项目、线程池 ID 如果由多个词组成,建议以 - 进行分割。比如message-center。
::: :::
@ -107,7 +107,7 @@ public class ThreadPoolConfig {
通过 ThreadPoolBuilder 构建动态线程池,只有 threadFactory、threadPoolId 为必填项,其它参数会从 hippo4j-server 服务拉取。 通过 ThreadPoolBuilder 构建动态线程池,只有 threadFactory、threadPoolId 为必填项,其它参数会从 hippo4j-server 服务拉取。
:::tip :::note
创建线程池时建议填充实际的参数。如果在连接 Hippo4J Server 端失败时,会使用填充配置创建线程池。 创建线程池时建议填充实际的参数。如果在连接 Hippo4J Server 端失败时,会使用填充配置创建线程池。
::: :::

@ -21,7 +21,7 @@ docker run -d -p 6691:6691 --name hippo4j-server \
-e DATASOURCE_DB=hippo4j_manager \ -e DATASOURCE_DB=hippo4j_manager \
-e DATASOURCE_USERNAME=root \ -e DATASOURCE_USERNAME=root \
-e DATASOURCE_PASSWORD=root \ -e DATASOURCE_PASSWORD=root \
hippo4j/hippo4j-server hippo4j/hippo4j-server
``` ```
访问 Server 控制台,路径 `http://localhost:6691/index.html` 默认用户名密码admin / 123456 访问 Server 控制台,路径 `http://localhost:6691/index.html` 默认用户名密码admin / 123456
@ -33,10 +33,10 @@ hippo4j/hippo4j-server
方式一: 方式一:
```shell ```shell
# 进入到 hippo4j-server 工程路径下 # 进入到 hippo4j-server/hippo4j-bootstrap 工程路径下
mvn clean package -Dskip.spotless.apply=true mvn clean package -Dskip.spotless.apply=true
# 默认打包是打包的 tag 是 latest # 默认打包是打包的 tag 是 latest
docker build -t hippo4j/hippo4j-server ../hippo4j-server docker build -t hippo4j/hippo4j-server ../hippo4j-bootstrap
``` ```
方式二: 方式二:

@ -12,7 +12,7 @@ sidebar_position: 3
docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server
``` ```
> 如果没有 Docker可以使用源码编译的方式启动 [Hippo4J-Server](https://github.com/longtai-cn/hippo4j/tree/develop/hippo4j-server) 模块下 ServerApplication 应用类。 > 如果没有 Docker可以使用源码编译的方式启动 [Hippo4J-Server/Hippo4J-Bootstrap](https://github.com/longtai-cn/hippo4j/tree/develop/hippo4j-server/hippo4j-bootstrap) 模块下 ServerApplication 应用类。
启动示例项目,[hippo4j-spring-boot-starter-example](https://github.com/opengoofy/hippo4j/tree/develop/hippo4j-example/hippo4j-spring-boot-starter-example) 模块下 Hippo4JServerExampleApplication 应用类。 启动示例项目,[hippo4j-spring-boot-starter-example](https://github.com/opengoofy/hippo4j/tree/develop/hippo4j-example/hippo4j-spring-boot-starter-example) 模块下 Hippo4JServerExampleApplication 应用类。

@ -14,8 +14,8 @@
"write-heading-ids": "docusaurus write-heading-ids" "write-heading-ids": "docusaurus write-heading-ids"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "2.0.0-beta.21", "@docusaurus/core": "2.1.0",
"@docusaurus/preset-classic": "2.0.0-beta.21", "@docusaurus/preset-classic": "2.1.0",
"@mdx-js/react": "^1.6.22", "@mdx-js/react": "^1.6.22",
"clsx": "^1.1.1", "clsx": "^1.1.1",
"prism-react-renderer": "^1.3.3", "prism-react-renderer": "^1.3.3",
@ -23,7 +23,7 @@
"react-dom": "^17.0.2" "react-dom": "^17.0.2"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-beta.21" "@docusaurus/module-type-aliases": "2.1.0"
}, },
"browserslist": { "browserslist": {
"production": [ "production": [

@ -19,13 +19,11 @@ package cn.hippo4j.adapter.web;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.ByteConvertUtil; import cn.hippo4j.common.toolkit.ByteConvertUtil;
import cn.hippo4j.common.toolkit.MemoryUtil;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.core.executor.state.AbstractThreadPoolRuntime; import cn.hippo4j.core.executor.state.AbstractThreadPoolRuntime;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
/** /**
* Web thread pool run state handler. * Web thread pool run state handler.
*/ */
@ -34,16 +32,13 @@ public class WebThreadPoolRunStateHandler extends AbstractThreadPoolRuntime {
@Override @Override
public ThreadPoolRunStateInfo supplement(ThreadPoolRunStateInfo poolRunStateInfo) { public ThreadPoolRunStateInfo supplement(ThreadPoolRunStateInfo poolRunStateInfo) {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); long used = MemoryUtil.heapMemoryUsed();
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage(); long max = MemoryUtil.heapMemoryMax();
long used = heapMemoryUsage.getUsed(); String memoryProportion = StringUtil.newBuilder(
long max = heapMemoryUsage.getMax(); "已分配: ",
String memoryProportion = new StringBuilder() ByteConvertUtil.getPrintSize(used),
.append("已分配: ") " / 最大可用: ",
.append(ByteConvertUtil.getPrintSize(used)) ByteConvertUtil.getPrintSize(max));
.append(" / 最大可用: ")
.append(ByteConvertUtil.getPrintSize(max))
.toString();
poolRunStateInfo.setCurrentLoad(poolRunStateInfo.getCurrentLoad() + "%"); poolRunStateInfo.setCurrentLoad(poolRunStateInfo.getCurrentLoad() + "%");
poolRunStateInfo.setPeakLoad(poolRunStateInfo.getPeakLoad() + "%"); poolRunStateInfo.setPeakLoad(poolRunStateInfo.getPeakLoad() + "%");
poolRunStateInfo.setMemoryProportion(memoryProportion); poolRunStateInfo.setMemoryProportion(memoryProportion);

@ -22,87 +22,202 @@ package cn.hippo4j.common.constant;
* *
* @author Rongzhen Yan * @author Rongzhen Yan
*/ */
public interface HttpResponseCode { public class HttpResponseCode {
int SC_CONTINUE = 100; /* 2XX: generally "OK" */
int SC_SWITCHING_PROTOCOLS = 101; /**
* HTTP Status-Code 200: OK.
int SC_OK = 200; */
public static final int SC_OK = 200;
int SC_CREATED = 201;
/**
int SC_ACCEPTED = 202; * HTTP Status-Code 201: Created.
*/
int SC_NON_AUTHORITATIVE_INFORMATION = 203; public static final int SC_HTTP_CREATED = 201;
int SC_NO_CONTENT = 204; /**
* HTTP Status-Code 202: Accepted.
int SC_RESET_CONTENT = 205; */
public static final int SC_HTTP_ACCEPTED = 202;
int SC_PARTIAL_CONTENT = 206;
/**
int SC_MULTIPLE_CHOICES = 300; * HTTP Status-Code 203: Non-Authoritative Information.
*/
int SC_MOVED_PERMANENTLY = 301; public static final int SC_HTTP_NOT_AUTHORITATIVE = 203;
int SC_MOVED_TEMPORARILY = 302; /**
* HTTP Status-Code 204: No Content.
int SC_FOUND = 302; */
public static final int SC_HTTP_NO_CONTENT = 204;
int SC_SEE_OTHER = 303;
/**
int SC_NOT_MODIFIED = 304; * HTTP Status-Code 205: Reset Content.
*/
int SC_USE_PROXY = 305; public static final int SC_HTTP_RESET = 205;
int SC_TEMPORARY_REDIRECT = 307; /**
* HTTP Status-Code 206: Partial Content.
int SC_BAD_REQUEST = 400; */
public static final int SC_HTTP_PARTIAL = 206;
int SC_UNAUTHORIZED = 401;
/* 3XX: relocation/redirect */
int SC_PAYMENT_REQUIRED = 402;
/**
int SC_FORBIDDEN = 403; * HTTP Status-Code 300: Multiple Choices.
*/
int SC_NOT_FOUND = 404; public static final int SC_HTTP_MULT_CHOICE = 300;
int SC_METHOD_NOT_ALLOWED = 405; /**
* HTTP Status-Code 301: Moved Permanently.
int SC_NOT_ACCEPTABLE = 406; */
public static final int SC_HTTP_MOVED_PERM = 301;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
/**
int SC_REQUEST_TIMEOUT = 408; * HTTP Status-Code 302: Temporary Redirect.
*/
int SC_CONFLICT = 409; public static final int SC_HTTP_MOVED_TEMP = 302;
int SC_GONE = 410; /**
* HTTP Status-Code 303: See Other.
int SC_LENGTH_REQUIRED = 411; */
public static final int SC_HTTP_SEE_OTHER = 303;
int SC_PRECONDITION_FAILED = 412;
/**
int SC_REQUEST_ENTITY_TOO_LARGE = 413; * HTTP Status-Code 304: Not Modified.
*/
int SC_REQUEST_URI_TOO_LONG = 414; public static final int SC_HTTP_NOT_MODIFIED = 304;
int SC_UNSUPPORTED_MEDIA_TYPE = 415; /**
* HTTP Status-Code 305: Use Proxy.
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416; */
public static final int SC_HTTP_USE_PROXY = 305;
int SC_EXPECTATION_FAILED = 417;
/**
int SC_INTERNAL_SERVER_ERROR = 500; * HTTP 1.1 Status-Code 307: Temporary Redirect.
*/
int SC_NOT_IMPLEMENTED = 501; public static final int SC_HTTP_TEMP_REDIRECT = 307;
int SC_BAD_GATEWAY = 502; /**
* HTTP 1.1 Status-Code 308: Permanent Redirect
int SC_SERVICE_UNAVAILABLE = 503; */
public static final int SC_HTTP_PERMANENT_REDIRECT = 308;
int SC_GATEWAY_TIMEOUT = 504;
/* 4XX: client error */
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
/**
* HTTP Status-Code 400: Bad Request.
*/
public static final int SC_HTTP_BAD_REQUEST = 400;
/**
* HTTP Status-Code 401: Unauthorized.
*/
public static final int SC_HTTP_UNAUTHORIZED = 401;
/**
* HTTP Status-Code 402: Payment Required.
*/
public static final int SC_HTTP_PAYMENT_REQUIRED = 402;
/**
* HTTP Status-Code 403: Forbidden.
*/
public static final int SC_HTTP_FORBIDDEN = 403;
/**
* HTTP Status-Code 404: Not Found.
*/
public static final int SC_HTTP_NOT_FOUND = 404;
/**
* HTTP Status-Code 405: Method Not Allowed.
*/
public static final int SC_HTTP_BAD_METHOD = 405;
/**
* HTTP Status-Code 406: Not Acceptable.
*/
public static final int SC_HTTP_NOT_ACCEPTABLE = 406;
/**
* HTTP Status-Code 407: Proxy Authentication Required.
*/
public static final int SC_HTTP_PROXY_AUTH = 407;
/**
* HTTP Status-Code 408: Request Time-Out.
*/
public static final int SC_HTTP_CLIENT_TIMEOUT = 408;
/**
* HTTP Status-Code 409: Conflict.
*/
public static final int SC_HTTP_CONFLICT = 409;
/**
* HTTP Status-Code 410: Gone.
*/
public static final int SC_HTTP_GONE = 410;
/**
* HTTP Status-Code 411: Length Required.
*/
public static final int SC_HTTP_LENGTH_REQUIRED = 411;
/**
* HTTP Status-Code 412: Precondition Failed.
*/
public static final int SC_HTTP_PRECON_FAILED = 412;
/**
* HTTP Status-Code 413: Request Entity Too Large.
*/
public static final int SC_HTTP_ENTITY_TOO_LARGE = 413;
/**
* HTTP Status-Code 414: Request-URI Too Large.
*/
public static final int SC_HTTP_REQ_TOO_LONG = 414;
/**
* HTTP Status-Code 415: Unsupported Media Type.
*/
public static final int SC_HTTP_UNSUPPORTED_TYPE = 415;
/* 5XX: server error */
/**
* HTTP Status-Code 500: Internal Server Error.
*/
public static final int SC_HTTP_INTERNAL_ERROR = 500;
/**
* HTTP Status-Code 501: Not Implemented.
*/
public static final int SC_HTTP_NOT_IMPLEMENTED = 501;
/**
* HTTP Status-Code 502: Bad Gateway.
*/
public static final int SC_HTTP_BAD_GATEWAY = 502;
/**
* HTTP Status-Code 503: Service Unavailable.
*/
public static final int SC_HTTP_UNAVAILABLE = 503;
/**
* HTTP Status-Code 504: Gateway Timeout.
*/
public static final int SC_HTTP_GATEWAY_TIMEOUT = 504;
/**
* HTTP Status-Code 505: HTTP Version Not Supported.
*/
public static final int SC_HTTP_VERSION = 505;
public static boolean isOk(int code) {
return (code >= SC_OK && code < SC_HTTP_MULT_CHOICE) || code == SC_HTTP_NOT_MODIFIED;
}
} }

@ -17,30 +17,39 @@
package cn.hippo4j.common.enums; package cn.hippo4j.common.enums;
/**
* Enumeration of thread pool audit status.
*/
public enum VerifyEnum { public enum VerifyEnum {
/** /**
* unVerify * To verify
*/ */
TO_VERIFY(0, "待审核"), TO_VERIFY(0, "待审核"),
/** /**
* accept * Verify accept
*/ */
VERIFY_ACCEPT(1, "审核通过"), VERIFY_ACCEPT(1, "审核通过"),
/** /**
* reject * Verify reject
*/ */
VERIFY_REJECT(2, "审核拒绝"), VERIFY_REJECT(2, "审核拒绝"),
/** /**
* invalid * Verify invalid
*/ */
VERIFY_INVALID(3, "失效"); VERIFY_INVALID(3, "失效");
/**
* Verify status
*/
private final Integer verifyStatus; private final Integer verifyStatus;
/**
* Desc
*/
private final String desc; private final String desc;
VerifyEnum(Integer verifyStatus, String desc) { VerifyEnum(Integer verifyStatus, String desc) {

@ -22,7 +22,8 @@ import cn.hippo4j.common.function.Matcher;
import java.lang.reflect.Array; import java.lang.reflect.Array;
/** /**
* Array util. * Array util.<br>
* Refer to cn.hutool.core.util.ArrayUtil:<br>
*/ */
public class ArrayUtil { public class ArrayUtil {

@ -22,7 +22,6 @@ import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper; import com.github.dozermapper.core.Mapper;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.beans.BeanUtils;
import java.beans.IntrospectionException; import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
@ -30,7 +29,8 @@ import java.lang.reflect.Method;
import java.util.*; import java.util.*;
/** /**
* Bean util. * Bean util.<br>
* use com.github.dozermapper
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BeanUtil { public class BeanUtil {
@ -73,6 +73,13 @@ public class BeanUtil {
.orElse(null); .orElse(null);
} }
/**
* map to bean
*
* @param map source data
* @param clazz type
* @param toCamelCase key convert
*/
public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz, boolean toCamelCase) { public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz, boolean toCamelCase) {
if (clazz == null) { if (clazz == null) {
return null; return null;

@ -21,7 +21,8 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Collection util. * Collection util.<br>
* Refer to cn.hutool.core.collection.CollUtil:<br>
*/ */
public class CollectionUtil { public class CollectionUtil {

@ -46,14 +46,13 @@ public class ContentUtil {
} }
public static String getGroupKey(ThreadPoolParameter parameter) { public static String getGroupKey(ThreadPoolParameter parameter) {
StringBuilder stringBuilder = new StringBuilder(); return StringUtil.createBuilder()
String resultStr = stringBuilder.append(parameter.getTpId()) .append(parameter.getTpId())
.append(Constants.GROUP_KEY_DELIMITER) .append(Constants.GROUP_KEY_DELIMITER)
.append(parameter.getItemId()) .append(parameter.getItemId())
.append(Constants.GROUP_KEY_DELIMITER) .append(Constants.GROUP_KEY_DELIMITER)
.append(parameter.getTenantId()) .append(parameter.getTenantId())
.toString(); .toString();
return resultStr;
} }
public static String getGroupKey(String... parameters) { public static String getGroupKey(String... parameters) {

@ -23,9 +23,7 @@ import lombok.NoArgsConstructor;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Date; import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.TimeZone; import java.util.TimeZone;
/** /**

@ -23,7 +23,6 @@ import org.springframework.core.io.ClassPathResource;
import java.io.*; import java.io.*;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -52,36 +51,24 @@ public class FileUtil {
return resultReadStr; return resultReadStr;
} }
/**
* According to the line read
*
* @param path the path
* @param charset the charset
*/
public static List<String> readLines(String path, Charset charset) { public static List<String> readLines(String path, Charset charset) {
List<String> strList = new ArrayList<>(); List<String> strList = new ArrayList<>();
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
ClassPathResource classPathResource = new ClassPathResource(path); ClassPathResource classPathResource = new ClassPathResource(path);
try { try (
inputStreamReader = new InputStreamReader(classPathResource.getInputStream(), charset); InputStreamReader in = new InputStreamReader(classPathResource.getInputStream(), charset);
bufferedReader = new BufferedReader(inputStreamReader); BufferedReader reader = new BufferedReader(in)) {
String line; String line;
while ((line = bufferedReader.readLine()) != null) { while ((line = reader.readLine()) != null) {
strList.add(line); strList.add(line);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); throw new IllegalException("file read error", e);
throw new IllegalException("file read error");
} finally {
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (IOException e) {
throw new IllegalException("file read error");
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
throw new IllegalException("file read error");
}
}
} }
return strList; return strList;
} }

@ -24,6 +24,7 @@ import static cn.hippo4j.common.constant.Constants.GROUP_KEY_DELIMITER;
/** /**
* Group key. * Group key.
* Refer to com.alibaba.nacos.client.config.common.GroupKey:<br>
*/ */
public class GroupKey { public class GroupKey {

@ -47,10 +47,28 @@ public class IdUtil {
} }
/** /**
* toString * Returns a {@code String} object representing this {@code UUID}.
* *
* @param uuid UUID * <p> The UUID string representation is as described by this BNF:
* @return UUID String * <blockquote><pre>
* {@code
* UUID = <time_low> "-" <time_mid> "-"
* <time_high_and_version> "-"
* <variant_and_sequence> "-"
* <node>
* time_low = 4*<hexOctet>
* time_mid = 2*<hexOctet>
* time_high_and_version = 2*<hexOctet>
* variant_and_sequence = 2*<hexOctet>
* node = 6*<hexOctet>
* hexOctet = <hexDigit><hexDigit>
* hexDigit =
* "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
* | "a" | "b" | "c" | "d" | "e" | "f"
* | "A" | "B" | "C" | "D" | "E" | "F"
* }</pre></blockquote>
*
* @return A string representation of this {@code UUID}
*/ */
public static String toString(UUID uuid, boolean isSimple) { public static String toString(UUID uuid, boolean isSimple) {
long mostSigBits = uuid.getMostSignificantBits(); long mostSigBits = uuid.getMostSignificantBits();

@ -23,7 +23,8 @@ import java.util.Iterator;
import java.util.Objects; import java.util.Objects;
/** /**
* reference google guava * reference google guava<br>
* com.google.common.base.Joiner
*/ */
public class Joiner { public class Joiner {

@ -17,10 +17,7 @@
package cn.hippo4j.common.toolkit; package cn.hippo4j.common.toolkit;
import java.util.Collection; import java.util.*;
import java.util.Dictionary;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -151,6 +148,41 @@ public class MapUtil {
return val; return val;
} }
/**
* Fuzzy matching based on Key.
*
* @param sourceMap
* @param filters
* @return
*/
public static List<String> parseMapForFilter(Map<String, ?> sourceMap, String filters) {
List<String> resultList = new ArrayList<>();
if (CollectionUtil.isEmpty(sourceMap)) {
return resultList;
}
sourceMap.forEach((key, val) -> {
if (checkKey(key, filters)) {
resultList.add(key);
}
});
return resultList;
}
/**
* Match the characters you want to query.
*
* @param key
* @param filters
* @return
*/
private static boolean checkKey(String key, String filters) {
if (key.indexOf(filters) > -1) {
return true;
} else {
return false;
}
}
/** /**
* remove value, Thread safety depends on whether the Map is a thread-safe Map. * remove value, Thread safety depends on whether the Map is a thread-safe Map.
* *

@ -28,6 +28,7 @@ import java.util.List;
/** /**
* MD5 util. * MD5 util.
* Refer to com.alibaba.nacos.common.util.Md5Utils:<br>
*/ */
public class Md5Util { public class Md5Util {
@ -96,16 +97,12 @@ public class Md5Util {
sb.append(Constants.WORD_SEPARATOR); sb.append(Constants.WORD_SEPARATOR);
sb.append(dataIdGroupId[1]); sb.append(dataIdGroupId[1]);
// if have tenant, then set it // if have tenant, then set it
if (dataIdGroupId.length == DATA_ID_GROUP_ID_THREE_LEN) { boolean b = (dataIdGroupId.length == DATA_ID_GROUP_ID_THREE_LEN
if (StringUtil.isNotBlank(dataIdGroupId[2])) { || dataIdGroupId.length == DATA_ID_GROUP_ID_FOUR_LEN)
sb.append(Constants.WORD_SEPARATOR); && StringUtil.isNotBlank(dataIdGroupId[2]);
sb.append(dataIdGroupId[2]); if (b) {
} sb.append(Constants.WORD_SEPARATOR);
} else if (dataIdGroupId.length == DATA_ID_GROUP_ID_FOUR_LEN) { sb.append(dataIdGroupId[2]);
if (StringUtil.isNotBlank(dataIdGroupId[2])) {
sb.append(Constants.WORD_SEPARATOR);
sb.append(dataIdGroupId[2]);
}
} }
sb.append(Constants.LINE_SEPARATOR); sb.append(Constants.LINE_SEPARATOR);
} }

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.toolkit;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
/**
* memory util<br>
* the obtained information is not invalid, after a long wait, obtain it again
*
* @author liuwenhao
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MemoryUtil {
static MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
static MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
static MemoryUsage noHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
/**
* get used memory in heap
*
* @return long bytes
*/
public static long heapMemoryUsed() {
return heapMemoryUsage.getUsed();
}
/**
* get max memory in heap
*
* @return long bytes
*/
public static long heapMemoryMax() {
return heapMemoryUsage.getMax();
}
/**
* get free memory in heap
*
* @return long bytes
*/
public static long heapMemoryFree() {
return Math.subtractExact(heapMemoryMax(), heapMemoryUsed());
}
/**
* get used memory in no-heap
*
* @return long bytes
*/
public static long noHeapMemoryUsed() {
return noHeapMemoryUsage.getUsed();
}
/**
* get max memory in no-heap
*
* @return long bytes
*/
public static long noHeapMemoryMax() {
return noHeapMemoryUsage.getMax();
}
/**
* get free memory in no-heap
*
* @return long bytes
*/
public static long noHeapMemoryFree() {
return Math.subtractExact(noHeapMemoryMax(), noHeapMemoryUsed());
}
}

@ -29,10 +29,13 @@ import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
/** /**
* Reflect util. * Reflect util.<br>
* Refer to cn.hutool.core.util.ReflectUtil:<br>
* {@link this#getFieldsDirectly(Class, boolean)} <br>
* {@link this#setFieldValue(Object, Field, Object)} <br>
* {@link this#getDefaultValue(Class)} <br>
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ReflectUtil { public class ReflectUtil {

@ -21,7 +21,11 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
* String util. * String util.<br>
* Refer to cn.hutool.core.util.StrUtil:<br>
* {@link this#toSymbolCase(CharSequence, char)}<br>
* {@link this#toCamelCase(CharSequence, char)}<br>
* {@link this#subBefore(String, String)}<br>
*/ */
public class StringUtil { public class StringUtil {
@ -53,8 +57,9 @@ public class StringUtil {
/** /**
* Returns {@code true} if the given string is null or is the empty string. * Returns {@code true} if the given string is null or is the empty string.
* * <p>
* this method has been deprecated, use isEmpty() instead. * this method has been deprecated, use isEmpty() instead.
*
* @param str * @param str
* @return * @return
*/ */
@ -302,7 +307,8 @@ public class StringUtil {
* StringUtils.split("abc def", " ") = ["abc", "def"] * StringUtils.split("abc def", " ") = ["abc", "def"]
* StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"] * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
* </pre> * </pre>
* @param str the String to parse, may be null *
* @param str the String to parse, may be null
* @param separatorChars the characters used as the delimiters, * @param separatorChars the characters used as the delimiters,
* @return an array of parsed Strings * @return an array of parsed Strings
*/ */

@ -319,7 +319,7 @@ public class HttpUtil {
} }
connection.connect(); connection.connect();
JdkHttpClientResponse response = new JdkHttpClientResponse(connection); JdkHttpClientResponse response = new JdkHttpClientResponse(connection);
if (HttpResponseCode.SC_OK != response.getStatusCode()) { if (!HttpResponseCode.isOk(response.getStatusCode())) {
String msg = String.format("HttpPost response code error. [code] %s [url] %s [body] %s", response.getStatusCode(), connection.getURL(), response.getBodyString()); String msg = String.format("HttpPost response code error. [code] %s [url] %s [body] %s", response.getStatusCode(), connection.getURL(), response.getBodyString());
throw new ServiceException(msg); throw new ServiceException(msg);
} }

@ -15,10 +15,8 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.config.toolkit; package cn.hippo4j.common.toolkit;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.CollectionUtil;
import org.junit.Test; import org.junit.Test;
import java.util.HashMap; import java.util.HashMap;
@ -66,9 +64,9 @@ public class MapUtilTest {
@Test @Test
public void computeIfAbsentNotExistKeyTest() { public void computeIfAbsentNotExistKeyTest() {
Map<Object, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("abc", "123"); map.put("abc", "123");
BiFunction<String, String, String> mappingFunction = (a, b) -> a + b; BiFunction<String, String, Object> mappingFunction = (a, b) -> a + b;
try { try {
MapUtil.computeIfAbsent(map, null, mappingFunction, "param1", "param2"); MapUtil.computeIfAbsent(map, null, mappingFunction, "param1", "param2");
} catch (Exception e) { } catch (Exception e) {
@ -93,9 +91,9 @@ public class MapUtilTest {
@Test @Test
public void computeIfAbsentNotExistParam1Test() { public void computeIfAbsentNotExistParam1Test() {
Map<Object, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("abc", "123"); map.put("abc", "123");
BiFunction<String, String, String> mappingFunction = (a, b) -> a + b; BiFunction<String, String, Object> mappingFunction = (a, b) -> a + b;
try { try {
MapUtil.computeIfAbsent(map, "abc", mappingFunction, null, "param2"); MapUtil.computeIfAbsent(map, "abc", mappingFunction, null, "param2");
} catch (Exception e) { } catch (Exception e) {
@ -107,9 +105,9 @@ public class MapUtilTest {
@Test @Test
public void computeIfAbsentNotExistParam2Test() { public void computeIfAbsentNotExistParam2Test() {
Map<Object, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("abc", "123"); map.put("abc", "123");
BiFunction<String, String, String> mappingFunction = (a, b) -> a + b; BiFunction<String, String, Object> mappingFunction = (a, b) -> a + b;
try { try {
MapUtil.computeIfAbsent(map, "abc", mappingFunction, "param1", null); MapUtil.computeIfAbsent(map, "abc", mappingFunction, "param1", null);
} catch (Exception e) { } catch (Exception e) {
@ -121,18 +119,18 @@ public class MapUtilTest {
@Test @Test
public void computeIfAbsentValNotNullTest() { public void computeIfAbsentValNotNullTest() {
Map<Object, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("abc", "123"); map.put("abc", "123");
BiFunction<String, String, String> mappingFunction = (a, b) -> a + b; BiFunction<String, String, Object> mappingFunction = (a, b) -> a + b;
Object ret = MapUtil.computeIfAbsent(map, "abc", mappingFunction, "param1", "param2"); Object ret = MapUtil.computeIfAbsent(map, "abc", mappingFunction, "param1", "param2");
Assert.isTrue(Objects.equals("123", String.valueOf(ret))); Assert.isTrue(Objects.equals("123", String.valueOf(ret)));
} }
@Test @Test
public void computeIfAbsentValIsNullTest() { public void computeIfAbsentValIsNullTest() {
Map<Object, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("abc", "123"); map.put("abc", "123");
BiFunction<String, String, String> mappingFunction = (a, b) -> a + b; BiFunction<String, String, Object> mappingFunction = (a, b) -> a + b;
Object ret = MapUtil.computeIfAbsent(map, "xyz", mappingFunction, "param1", "param2"); Object ret = MapUtil.computeIfAbsent(map, "xyz", mappingFunction, "param1", "param2");
Assert.isTrue(Objects.equals("param1param2", String.valueOf(ret))); Assert.isTrue(Objects.equals("param1param2", String.valueOf(ret)));
} }

@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.common.toolkit;
import org.junit.Assert;
import org.junit.Test;
public class MemoryUtilTest {
@Test
public void heapMemoryUsed() {
long memoryUsed = MemoryUtil.heapMemoryUsed();
Assert.assertNotEquals(0, memoryUsed);
}
@Test
public void heapMemoryMax() {
long memoryUsed = MemoryUtil.heapMemoryMax();
Assert.assertNotEquals(0, memoryUsed);
}
@Test
public void heapMemoryFree() {
long memoryUsed = MemoryUtil.heapMemoryFree();
Assert.assertNotEquals(0, memoryUsed);
}
@Test
public void noHeapMemoryUsed() {
long memoryUsed = MemoryUtil.noHeapMemoryUsed();
Assert.assertNotEquals(0, memoryUsed);
}
@Test
public void noHeapMemoryMax() {
long memoryUsed = MemoryUtil.noHeapMemoryMax();
Assert.assertNotEquals(0, memoryUsed);
}
@Test
public void noHeapMemoryFree() {
long memoryUsed = MemoryUtil.noHeapMemoryFree();
Assert.assertNotEquals(0, memoryUsed);
}
}

@ -72,14 +72,14 @@ public class HttpUtilsTest {
Assert.assertNotNull(data); Assert.assertNotNull(data);
} }
@Test @Test(expected = SocketTimeoutException.class)
public void testRestApiPostTimeout() { public void testRestApiPostTimeout() {
String loginUrl = postUrl + "auth/login"; String loginUrl = postUrl + "auth/login";
LoginInfo loginInfo = new LoginInfo(); LoginInfo loginInfo = new LoginInfo();
loginInfo.setPassword("hippo4j"); loginInfo.setPassword("hippo4j");
loginInfo.setUsername("hippo4j"); loginInfo.setUsername("hippo4j");
loginInfo.setRememberMe(1); loginInfo.setRememberMe(1);
Assert.assertThrows(SocketTimeoutException.class, () -> HttpUtil.post(loginUrl, loginInfo, 1, Result.class)); HttpUtil.post(loginUrl, loginInfo, 1, Result.class);
} }
@Test @Test

@ -1,82 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.config.toolkit;
import cn.hippo4j.common.toolkit.CollectionUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
/**
* Map util.
*/
public class MapUtil {
public static Object computeIfAbsent(Map target, Object key, BiFunction mappingFunction, Object param1, Object param2) {
Objects.requireNonNull(target, "target");
Objects.requireNonNull(key, "key");
Objects.requireNonNull(mappingFunction, "mappingFunction");
Objects.requireNonNull(param1, "param1");
Objects.requireNonNull(param2, "param2");
Object val = target.get(key);
if (val == null) {
Object ret = mappingFunction.apply(param1, param2);
target.put(key, ret);
return ret;
}
return val;
}
/**
* Fuzzy matching based on Key.
*
* @param sourceMap
* @param filters
* @return
*/
public static List<String> parseMapForFilter(Map<String, ?> sourceMap, String filters) {
List<String> resultList = new ArrayList<>();
if (CollectionUtil.isEmpty(sourceMap)) {
return resultList;
}
sourceMap.forEach((key, val) -> {
if (checkKey(key, filters)) {
resultList.add(key);
}
});
return resultList;
}
/**
* Match the characters you want to query.
*
* @param key
* @param filters
* @return
*/
private static boolean checkKey(String key, String filters) {
if (key.indexOf(filters) > -1) {
return true;
} else {
return false;
}
}
}

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
.editor-container[data-v-7505e034]{height:82vh;overflow:auto}

File diff suppressed because one or more lines are too long

@ -1,893 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="216"
height="144"
id="svg4136"
version="1.1"
inkscape:version="0.91 r"
sodipodi:docname="jsoneditor-icons.svg">
<title
id="title6512">JSON Editor Icons</title>
<metadata
id="metadata4148">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>JSON Editor Icons</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4146" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview4144"
showgrid="true"
inkscape:zoom="4"
inkscape:cx="97.217248"
inkscape:cy="59.950227"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid4640"
empspacing="24" />
</sodipodi:namedview>
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<g
id="g4394">
<rect
x="4"
y="4"
width="16"
height="16"
id="svg_1"
style="fill:#1aae1c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0"
x="28.000006"
y="3.999995"
width="16"
height="16"
id="svg_1-7" />
<rect
id="rect4165"
height="16"
width="16"
y="3.999995"
x="52.000004"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="172.00002"
y="3.9999852"
width="16"
height="16"
id="rect4175" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="196"
y="3.999995"
width="16"
height="16"
id="rect4175-3" />
<g
style="stroke:none"
id="g4299">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
style="stroke:none"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
id="g4299-3">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-0"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1-9"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="7.0000048"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5" />
<rect
id="rect4354"
height="6.9999905"
width="6.9999909"
y="10.00001"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
x="58.000004"
y="10.000005"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5-7" />
<g
id="g4378">
<rect
id="svg_1-7-5-3"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4374" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4376" />
</g>
<g
id="g4383"
transform="matrix(1,0,0,-1,-23.999995,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4385" />
<rect
id="rect4387"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4389"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
y="3.9999199"
x="76"
height="16"
width="16"
id="rect3754-4"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351"
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351-9"
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="3.9999199"
x="100"
height="16"
width="16"
id="rect3754-25"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987"
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987-1"
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="124"
height="16"
width="16"
id="rect3754-73"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3780"
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3782"
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="148"
height="16"
width="16"
id="rect3754-35"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2"
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2-8"
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</g>
<rect
x="4"
y="27.999994"
width="16"
height="16"
id="rect4432"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0"
x="28.000006"
y="27.99999"
width="16"
height="16"
id="rect4434" />
<rect
id="rect4436"
height="16"
width="16"
y="27.99999"
x="52.000004"
style="fill:#d3d3d3;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="172.00002"
y="27.999981"
width="16"
height="16"
id="rect4446" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="196"
y="27.99999"
width="16"
height="16"
id="rect4448" />
<g
id="g4466"
style="stroke:none"
transform="translate(0,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4468"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4470"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,35.999996)"
id="g4472"
style="stroke:none">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4474"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4476"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="31"
width="6.9999909"
height="6.9999905"
id="rect4478" />
<rect
id="rect4480"
height="6.9999905"
width="6.9999909"
y="34.000008"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
x="58.000004"
y="34.000004"
width="6.9999909"
height="6.9999905"
id="rect4482" />
<g
id="g4484"
transform="translate(0,23.999995)">
<rect
id="rect4486"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4488" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4490" />
</g>
<g
id="g4492"
transform="matrix(1,0,0,-1,-23.999995,47.99999)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4494" />
<rect
id="rect4496"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4498"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-8"
width="16"
height="16"
x="76"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10448,30.015537 -0.0156,1.4063 c 3.02668,-0.2402 0.33007,3.6508 2.48438,4.5781 -2.18695,1.0938 0.49191,4.90688 -2.45313,4.57808 l -0.0156,1.4219 c 5.70827,0.559 1.03263,-5.10048 4.70313,-5.26558 l 0,-1.4063 c -3.61304,-0.027 1.11893,-5.707 -4.70313,-5.3125 z"
id="path4351-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 82.78126,29.998237 0.0156,1.4063 c -3.02668,-0.2402 -0.33008,3.6507 -2.48438,4.5781 2.18694,1.0938 -0.49191,4.90688 2.45313,4.57808 l 0.0156,1.4219 c -5.70828,0.559 -1.03264,-5.10038 -4.70313,-5.26558 l 0,-1.4063 c 3.61303,-0.027 -1.11893,-5.7071 4.70313,-5.3125 z"
id="path4351-9-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-65"
width="16"
height="16"
x="100"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 103.719,29.671937 0,12.71878 3.03125,0 0,-1.5313 -1.34375,0 0,-9.62498 1.375,0 0,-1.5625 z"
id="path2987-8"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 112.2185,29.671937 0,12.71878 -3.03125,0 0,-1.5313 1.34375,0 0,-9.62498 -1.375,0 0,-1.5625 z"
id="path2987-1-9"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-92"
width="16"
height="16"
x="124"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 126.2824,41.602917 1.78957,0 1.14143,-2.86408 5.65364,0 1.14856,2.86408 1.76565,0 -4.78687,-11.16108 -1.91902,0 z"
id="path3780-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
d="m 129.72704,37.478837 4.60852,0.01 -2.30426,-5.5498 z"
id="path3782-2"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-47"
width="16"
height="16"
x="148"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 156.47656,29.891737 0,2.1797 0.46093,2.3984 1.82813,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 152.51562,29.890637 0,2.1797 0.46094,2.3984 1.82812,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-8-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
id="svg_1-7-2"
height="1.9999961"
width="11.999996"
y="64"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="svg_1-7-2-2"
height="2.9999905"
width="2.9999907"
y="52"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="52"
width="2.9999907"
height="2.9999905"
id="rect4561" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="80.000008"
y="58"
width="2.9999907"
height="2.9999905"
id="rect4563" />
<rect
id="rect4565"
height="2.9999905"
width="2.9999907"
y="58"
x="85.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="rect4567"
height="2.9999905"
width="2.9999907"
y="64"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="64"
width="2.9999907"
height="2.9999905"
id="rect4569" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4571"
cx="110.06081"
cy="57.939209"
r="4.7438836" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="116.64566"
y="-31.79752"
width="4.229713"
height="6.4053884"
id="rect4563-2"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
<path
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125,56 138.77027,56.095 132,64 Z"
id="path4613"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615"
d="M 149,64 162.77027,63.905 156,56 Z"
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="54"
y="53"
width="11.999996"
height="1.9999961"
id="rect4638" />
<rect
id="svg_1-7-2-24"
height="1.9999957"
width="12.99999"
y="-56"
x="53"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
transform="matrix(0,1,-1,0,0,0)" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="53"
y="-66"
width="12.99999"
height="1.9999957"
id="rect4657" />
<rect
id="rect4659"
height="0.99999291"
width="11.999999"
y="57"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="88.000122"
width="11.999996"
height="1.9999961"
id="rect4661" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="76.000122"
width="2.9999907"
height="2.9999905"
id="rect4663" />
<rect
id="rect4665"
height="2.9999905"
width="2.9999907"
y="76.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
id="rect4667"
height="2.9999905"
width="2.9999907"
y="82.000122"
x="80.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="85.000008"
y="82.000122"
width="2.9999907"
height="2.9999905"
id="rect4669" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="88.000122"
width="2.9999907"
height="2.9999905"
id="rect4671" />
<rect
id="rect4673"
height="2.9999905"
width="2.9999907"
y="88.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<circle
r="4.7438836"
cy="81.939331"
cx="110.06081"
id="circle4675"
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect4677"
height="6.4053884"
width="4.229713"
y="-14.826816"
x="133.6163"
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4679"
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
id="path4681"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<rect
id="rect4683"
height="1.9999961"
width="11.999996"
y="77.000122"
x="54"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="77.000122"
y="-56"
width="12.99999"
height="1.9999957"
id="rect4685" />
<rect
id="rect4687"
height="1.9999957"
width="12.99999"
y="-66"
x="77.000122"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="81.000122"
width="11.999999"
height="0.99999291"
id="rect4689" />
<rect
id="rect4761-1"
height="1.9999945"
width="15.99999"
y="101"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-0"
height="1.9999945"
width="15.99999"
y="105"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-7"
height="1.9999945"
width="9"
y="109"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1"
height="1.9999945"
width="12"
y="125"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4"
height="1.9999945"
width="10"
y="137"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4"
height="1.9999945"
width="10"
y="129"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4-3"
height="1.9999945"
width="9"
y="133"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
id="path3055-0-77" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9850574,108.015 14.0298856,-0.03"
id="path5244-5-0-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9849874,132.015 14.0298866,-0.03"
id="path5244-5-0-5-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138-12" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1-3" />
<path
id="path6191"
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
id="path6193" />
<path
id="path6195"
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4500"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073242"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
inkscape:transform-center-x="-1.2779026" />
<path
inkscape:transform-center-x="1.277902"
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073242"
sodipodi:cx="-36.611614"
sodipodi:sides="3"
id="path4502"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="scale(-1,1)" />
<path
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073212"
sodipodi:cx="11.55581"
sodipodi:sides="3"
id="path4504"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="matrix(0,1,-1,0,72.0074,71.7877)"
inkscape:transform-center-y="1.2779029" />
<path
inkscape:transform-center-y="-1.2779026"
transform="matrix(0,-1,-1,0,96,96)"
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4506"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073212"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615-5"
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,55 0,6 2,0 0,-6"
id="path4300"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,62 0,2 2,0 0,-2"
id="path4300-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</svg>

Before

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2fd02e04"],{"64b7":function(e,t,n){"use strict";n("de5f")},ab3b:function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-container"},[n("split-pane",{attrs:{split:"vertical"},on:{resize:e.resize}},[n("template",{slot:"paneL"},[n("el-input",{attrs:{type:"textarea",rows:36,placeholder:"请输入内容",clearable:""},on:{change:e.originChange},model:{value:e.originText,callback:function(t){e.originText=t},expression:"originText"}})],1),e._v(" "),n("template",{slot:"paneR"},[n("div",{staticClass:"editor-container"},[n("JSONEditor",{attrs:{json:e.formatedValue}})],1)])],2)],1)},i=[],o=n("19ab"),r=n.n(o),s=n("33c3"),c={name:"JsonFormat",components:{splitPane:r.a,JSONEditor:s["a"]},data:function(){return{originText:"",formatedValue:""}},watch:{originText:function(e){try{this.formatedValue=JSON.parse(e)}catch(t){}}},methods:{resize:function(){},originChange:function(e){}}},l=c,u=(n("64b7"),n("2877")),p=Object(u["a"])(l,a,i,!1,null,"7505e034",null);t["default"]=p.exports},de5f:function(e,t,n){}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -21,6 +21,8 @@ import cn.hippo4j.common.model.ManyThreadPoolRunStateInfo;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.BeanUtil; import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.ByteConvertUtil; import cn.hippo4j.common.toolkit.ByteConvertUtil;
import cn.hippo4j.common.toolkit.MemoryUtil;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.core.executor.DynamicThreadPoolExecutor; import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
import cn.hippo4j.core.executor.DynamicThreadPoolWrapper; import cn.hippo4j.core.executor.DynamicThreadPoolWrapper;
import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage; import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
@ -30,9 +32,6 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import static cn.hippo4j.core.toolkit.IdentifyUtil.CLIENT_IDENTIFICATION_VALUE; import static cn.hippo4j.core.toolkit.IdentifyUtil.CLIENT_IDENTIFICATION_VALUE;
@ -50,16 +49,13 @@ public class ThreadPoolRunStateHandler extends AbstractThreadPoolRuntime {
@Override @Override
public ThreadPoolRunStateInfo supplement(ThreadPoolRunStateInfo poolRunStateInfo) { public ThreadPoolRunStateInfo supplement(ThreadPoolRunStateInfo poolRunStateInfo) {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); long used = MemoryUtil.heapMemoryUsed();
MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage(); long max = MemoryUtil.heapMemoryMax();
long used = heapMemoryUsage.getUsed(); String memoryProportion = StringUtil.newBuilder(
long max = heapMemoryUsage.getMax(); "已分配: ",
String memoryProportion = new StringBuilder() ByteConvertUtil.getPrintSize(used),
.append("已分配: ") " / 最大可用: ",
.append(ByteConvertUtil.getPrintSize(used)) ByteConvertUtil.getPrintSize(max));
.append(" / 最大可用: ")
.append(ByteConvertUtil.getPrintSize(max))
.toString();
poolRunStateInfo.setCurrentLoad(poolRunStateInfo.getCurrentLoad() + "%"); poolRunStateInfo.setCurrentLoad(poolRunStateInfo.getCurrentLoad() + "%");
poolRunStateInfo.setPeakLoad(poolRunStateInfo.getPeakLoad() + "%"); poolRunStateInfo.setPeakLoad(poolRunStateInfo.getPeakLoad() + "%");
String ipAddress = hippo4JInetUtils.findFirstNonLoopBackHostInfo().getIpAddress(); String ipAddress = hippo4JInetUtils.findFirstNonLoopBackHostInfo().getIpAddress();

@ -112,6 +112,9 @@ public class ThreadPoolBuilder implements Builder<ThreadPoolExecutor> {
public ThreadPoolBuilder maxPoolNum(int maxPoolSize) { public ThreadPoolBuilder maxPoolNum(int maxPoolSize) {
this.maxPoolSize = maxPoolSize; this.maxPoolSize = maxPoolSize;
if (maxPoolSize < this.corePoolSize) {
this.corePoolSize = maxPoolSize;
}
return this; return this;
} }
@ -228,6 +231,7 @@ public class ThreadPoolBuilder implements Builder<ThreadPoolExecutor> {
/** /**
* Create dynamic thread pool by thread pool id * Create dynamic thread pool by thread pool id
*
* @param threadPoolId threadPoolId * @param threadPoolId threadPoolId
* @return ThreadPoolExecutor * @return ThreadPoolExecutor
*/ */

@ -17,6 +17,9 @@
package cn.hippo4j.core.proxy; package cn.hippo4j.core.proxy;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@ -24,6 +27,7 @@ import java.util.concurrent.atomic.AtomicLong;
/** /**
* Rejected proxy util. * Rejected proxy util.
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RejectedProxyUtil { public class RejectedProxyUtil {
/** /**
@ -35,11 +39,10 @@ public class RejectedProxyUtil {
* @return * @return
*/ */
public static RejectedExecutionHandler createProxy(RejectedExecutionHandler rejectedExecutionHandler, String threadPoolId, AtomicLong rejectedNum) { public static RejectedExecutionHandler createProxy(RejectedExecutionHandler rejectedExecutionHandler, String threadPoolId, AtomicLong rejectedNum) {
RejectedExecutionHandler rejectedProxy = (RejectedExecutionHandler) Proxy return (RejectedExecutionHandler) Proxy
.newProxyInstance( .newProxyInstance(
rejectedExecutionHandler.getClass().getClassLoader(), rejectedExecutionHandler.getClass().getClassLoader(),
new Class[]{RejectedExecutionHandler.class}, new Class[]{RejectedExecutionHandler.class},
new RejectedProxyInvocationHandler(rejectedExecutionHandler, threadPoolId, rejectedNum)); new RejectedProxyInvocationHandler(rejectedExecutionHandler, threadPoolId, rejectedNum));
return rejectedProxy;
} }
} }

@ -15,10 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.core.toolkit.inet; package cn.hippo4j.core.toolkit;
import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.config.ApplicationContextHolder;
import org.springframework.beans.factory.ListableBeanFactory; import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.AbstractApplicationContext;
@ -28,35 +29,25 @@ import java.lang.annotation.Annotation;
import java.util.Optional; import java.util.Optional;
/** /**
* {@link DynamicThreadPoolAnnotationUtil} SpringBoot. * Adapted to an earlier version of SpringBoot.
*
* <p>Spring version >= 5.2.0 , SpringBoot version 2.2.0.RELEASE
* {@link ListableBeanFactory#findAnnotationOnBean(java.lang.String, java.lang.Class)}
*
* <p>, , Spring .
* , Spring version < 5.3.14 , SpringBoot version < 2.6.2
*
* @author chen.ma
* @date 2022/1/5 21:15
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DynamicThreadPoolAnnotationUtil { public class DynamicThreadPoolAnnotationUtil {
/** /**
* {@param beanName} {@param annotationType} . * Check for the existence of {@param annotationType} based on {@param beanName}.
* *
* @param beanName * @param beanName bean name
* @param annotationType * @param annotationType annotation class
* @param <A> * @param <A> the Annotation type
* @return
*/ */
public static <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) { public static <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) {
AbstractApplicationContext context = (AbstractApplicationContext) ApplicationContextHolder.getInstance(); AbstractApplicationContext context = (AbstractApplicationContext) ApplicationContextHolder.getInstance();
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
A annotation = Optional.ofNullable(beanFactory) return Optional.of(beanFactory)
.map(each -> (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName)) .map(each -> (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName))
.map(definition -> definition.getResolvedFactoryMethod()) .map(RootBeanDefinition::getResolvedFactoryMethod)
.map(factoryMethod -> AnnotationUtils.getAnnotation(factoryMethod, annotationType)) .map(factoryMethod -> AnnotationUtils.getAnnotation(factoryMethod, annotationType))
.orElse(null); .orElse(null);
return annotation;
} }
} }

@ -22,7 +22,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
* System clock. * System clock.<br>
* Refer to cn.hutool.core.date.SystemClock<br>
*/ */
public class SystemClock { public class SystemClock {

@ -35,7 +35,8 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* Inet utils. * Inet utils.<br>
* Refer to org.springframework.cloud.commons.util.InetUtils<br>
*/ */
public class InetUtils implements Closeable { public class InetUtils implements Closeable {
@ -80,7 +81,7 @@ public class InetUtils implements Closeable {
this.log.trace("Testing interface: " + ifc.getDisplayName()); this.log.trace("Testing interface: " + ifc.getDisplayName());
if (ifc.getIndex() < lowest || result == null) { if (ifc.getIndex() < lowest || result == null) {
lowest = ifc.getIndex(); lowest = ifc.getIndex();
} else if (result != null) { } else {
continue; continue;
} }
// @formatter:off // @formatter:off

@ -0,0 +1,52 @@
# \u4EE5\u4E0B\u5185\u5BB9\u590D\u5236\u5230 apollo \u914D\u7F6E\u6587\u4EF6\u4E2D
# Copy the following to the apollo configuration file
spring.dynamic.thread-pool.tomcat.core-pool-size=64
spring.dynamic.thread-pool.tomcat.maximum-pool-size=128
spring.dynamic.thread-pool.tomcat.keep-alive-time=1000
spring.dynamic.thread-pool.tomcat.enable=true
spring.dynamic.thread-pool.default-executor.core-pool-size=1
spring.dynamic.thread-pool.default-executor.maximum-pool-size=2
spring.dynamic.thread-pool.default-executor.blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.default-executor.execute-time-out=100
spring.dynamic.thread-pool.default-executor.keep-alive-time=6691
spring.dynamic.thread-pool.default-executor.queue-capacity=1
spring.dynamic.thread-pool.default-executor.rejected-handler=AbortPolicy
spring.dynamic.thread-pool.default-executor.active-alarm=90
spring.dynamic.thread-pool.default-executor.capacity-alarm=85
spring.dynamic.thread-pool.default-executor.alarm=true
spring.dynamic.thread-pool.default-executor.allow-core-thread-time-out=true
spring.dynamic.thread-pool.default-executor.notify.interval=5
spring.dynamic.thread-pool.default-executor.notify.receives=chen.ma
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ec3be378-6c99-45d2-a147-b400c7e94a08
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -9,7 +9,7 @@ apollo.bootstrap.namespaces=application
apollo.bootstrap.eagerLoad.enabled=true apollo.bootstrap.eagerLoad.enabled=true
spring.profiles.active=dev spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example spring.application.name=hippo4j-config-apollo-spring-boot-1x-starter-example
management.security.enabled=false management.security.enabled=false
management.context-path=/actuator management.context-path=/actuator
@ -17,7 +17,11 @@ management.context-path=/actuator
spring.dynamic.thread-pool.enable=true spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=true spring.dynamic.thread-pool.banner=true
spring.dynamic.thread-pool.check-state-interval=5 spring.dynamic.thread-pool.check-state-interval=5
spring.dynamic.thread-pool.collect-type=micrometer spring.dynamic.thread-pool.monitor.enable=true
spring.dynamic.thread-pool.monitor.collect-types=micrometer
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff
@ -25,33 +29,33 @@ spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b
spring.dynamic.thread-pool.apollo.namespace=application spring.dynamic.thread-pool.apollo.namespace=application
spring.dynamic.thread-pool.config-file-type=properties spring.dynamic.thread-pool.config-file-type=properties
spring.dynamic.thread-pool.executors[0].active-alarm = 80 spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].alarm = true spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out = true spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].blocking-queue = LinkedBlockingQueue spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].capacity-alarm = 80 spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].core-pool-size = 1 spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out = 1000 spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].keep-alive-time = 6691 spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].maximum-pool-size = 1 spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].notify.interval = 8 spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].notify.receives = chen.ma spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].queue-capacity = 1 spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].rejected-handler = AbortPolicy spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].thread-name-prefix = message-consume spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].thread-pool-id = message-consume spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].active-alarm = 80 spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].alarm = true spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out = true spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].blocking-queue = LinkedBlockingQueue spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].capacity-alarm = 80 spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].core-pool-size = 1 spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out = 1000 spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].keep-alive-time = 6691 spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].maximum-pool-size = 1 spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].notify.interval = 8 spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].notify.receives = chen.ma spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].queue-capacity = 1 spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].rejected-handler = AbortPolicy spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].thread-name-prefix = message-produce spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].thread-pool-id = message-produce spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -0,0 +1,52 @@
# \u4EE5\u4E0B\u5185\u5BB9\u590D\u5236\u5230 apollo \u914D\u7F6E\u6587\u4EF6\u4E2D
# Copy the following to the apollo configuration file
spring.dynamic.thread-pool.tomcat.core-pool-size=64
spring.dynamic.thread-pool.tomcat.maximum-pool-size=128
spring.dynamic.thread-pool.tomcat.keep-alive-time=1000
spring.dynamic.thread-pool.tomcat.enable=true
spring.dynamic.thread-pool.default-executor.core-pool-size=1
spring.dynamic.thread-pool.default-executor.maximum-pool-size=2
spring.dynamic.thread-pool.default-executor.blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.default-executor.execute-time-out=100
spring.dynamic.thread-pool.default-executor.keep-alive-time=6691
spring.dynamic.thread-pool.default-executor.queue-capacity=1
spring.dynamic.thread-pool.default-executor.rejected-handler=AbortPolicy
spring.dynamic.thread-pool.default-executor.active-alarm=90
spring.dynamic.thread-pool.default-executor.capacity-alarm=85
spring.dynamic.thread-pool.default-executor.alarm=true
spring.dynamic.thread-pool.default-executor.allow-core-thread-time-out=true
spring.dynamic.thread-pool.default-executor.notify.interval=5
spring.dynamic.thread-pool.default-executor.notify.receives=chen.ma
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ec3be378-6c99-45d2-a147-b400c7e94a08
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -1,4 +1,3 @@
# Configuration reference: https://hippo4j.cn/pages/2f674h
server.port=8091 server.port=8091
server.servlet.context-path=/example server.servlet.context-path=/example
@ -10,7 +9,7 @@ apollo.bootstrap.namespaces=application
apollo.bootstrap.eagerLoad.enabled=true apollo.bootstrap.eagerLoad.enabled=true
spring.profiles.active=dev spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example spring.application.name=hippo4j-config-apollo-spring-boot-starter-example
management.metrics.export.prometheus.enabled=true management.metrics.export.prometheus.enabled=true
management.server.port=29998 management.server.port=29998
@ -19,29 +18,49 @@ management.endpoints.web.exposure.include=*
spring.dynamic.thread-pool.enable=true spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=true spring.dynamic.thread-pool.banner=true
spring.dynamic.thread-pool.check-state-interval=3 spring.dynamic.thread-pool.check-state-interval=3
spring.dynamic.thread-pool.monitor.enable=true
spring.dynamic.thread-pool.monitor.collect-types=micrometer
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ac0426a5-c712-474c-9bff-72b8b8f5caff spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff
spring.dynamic.thread-pool.notify-platforms[1].platform=DING spring.dynamic.thread-pool.notify-platforms[1].platform=DING
spring.dynamic.thread-pool.notify-platforms[1].secret-key=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55 spring.dynamic.thread-pool.notify-platforms[1].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
spring.dynamic.thread-pool.notify-platforms[2].platform=LARK spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
spring.dynamic.thread-pool.notify-platforms[2].secret-key=2cbf2808-3839-4c26-a04d-fd201dd51f9e spring.dynamic.thread-pool.notify-platforms[2].token=2cbf2808-3839-4c26-a04d-fd201dd51f9e
spring.dynamic.thread-pool.apollo.namespace=application spring.dynamic.thread-pool.apollo.namespace=application
spring.dynamic.thread-pool.config-file-type=properties spring.dynamic.thread-pool.config-file-type=properties
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=3 spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4 spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=4 spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].execute-time-out=1000 spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].blocking-queue=LinkedBlockingQueue spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=1000 spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].alarm=true spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80 spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80 spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8 spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -3,21 +3,37 @@ server.port=8888
spring.application.name=etcd spring.application.name=etcd
spring.dynamic.thread-pool.etcd.endpoints= http://127.0.0.1:2379 spring.dynamic.thread-pool.etcd.endpoints= http://127.0.0.1:2379
spring.dynamic.thread-pool.etcd.key= /thread spring.dynamic.thread-pool.etcd.key= /thread
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=3 spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4 spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=4 spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].execute-time-out=1000 spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].blocking-queue=LinkedBlockingQueue spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=1000 spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].alarm=true spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80 spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80 spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8 spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=111 spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ac0426a5-c712-474c-9bff-72b8b8f5caff spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff

@ -0,0 +1,52 @@
# \u4EE5\u4E0B\u5185\u5BB9\u590D\u5236\u5230 etcd \u914D\u7F6E\u6587\u4EF6\u4E2D
# Copy the following to the etcd configuration file
spring.dynamic.thread-pool.tomcat.core-pool-size=64
spring.dynamic.thread-pool.tomcat.maximum-pool-size=128
spring.dynamic.thread-pool.tomcat.keep-alive-time=1000
spring.dynamic.thread-pool.tomcat.enable=true
spring.dynamic.thread-pool.default-executor.core-pool-size=1
spring.dynamic.thread-pool.default-executor.maximum-pool-size=2
spring.dynamic.thread-pool.default-executor.blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.default-executor.execute-time-out=100
spring.dynamic.thread-pool.default-executor.keep-alive-time=6691
spring.dynamic.thread-pool.default-executor.queue-capacity=1
spring.dynamic.thread-pool.default-executor.rejected-handler=AbortPolicy
spring.dynamic.thread-pool.default-executor.active-alarm=90
spring.dynamic.thread-pool.default-executor.capacity-alarm=85
spring.dynamic.thread-pool.default-executor.alarm=true
spring.dynamic.thread-pool.default-executor.allow-core-thread-time-out=true
spring.dynamic.thread-pool.default-executor.notify.interval=5
spring.dynamic.thread-pool.default-executor.notify.receives=chen.ma
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ec3be378-6c99-45d2-a147-b400c7e94a08
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -6,7 +6,7 @@ management.security.enabled=false
management.context-path=/actuator management.context-path=/actuator
spring.profiles.active=dev spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example spring.application.name=hippo4j-config-nacos-spring-boot-1x-starter-example
spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.ext-config[0].data-id=hippo4j-nacos.yaml spring.cloud.nacos.config.ext-config[0].data-id=hippo4j-nacos.yaml
@ -15,17 +15,51 @@ spring.cloud.nacos.config.ext-config[0].refresh=true
spring.dynamic.thread-pool.enable=true spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=true spring.dynamic.thread-pool.banner=true
spring.dynamic.thread-pool.collect=true
spring.dynamic.thread-pool.collect-type=micrometer
spring.dynamic.thread-pool.check-state-interval=5 spring.dynamic.thread-pool.check-state-interval=5
spring.dynamic.thread-pool.monitor.enable=true
spring.dynamic.thread-pool.monitor.collect-types=micrometer
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ac0426a5-c712-474c-9bff-72b8b8f5caff spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff
spring.dynamic.thread-pool.notify-platforms[1].platform=DING spring.dynamic.thread-pool.notify-platforms[1].platform=DING
spring.dynamic.thread-pool.notify-platforms[1].secret-key=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55 spring.dynamic.thread-pool.notify-platforms[1].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
spring.dynamic.thread-pool.notify-platforms[2].platform=LARK spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
spring.dynamic.thread-pool.notify-platforms[2].secret-key=2cbf2808-3839-4c26-a04d-fd201dd51f9e spring.dynamic.thread-pool.notify-platforms[2].token=2cbf2808-3839-4c26-a04d-fd201dd51f9e
spring.dynamic.thread-pool.nacos.data-id=hippo4j-nacos.yaml spring.dynamic.thread-pool.nacos.data-id=hippo4j-nacos.yaml
spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP
spring.dynamic.thread-pool.config-file-type=yml spring.dynamic.thread-pool.config-file-type=yml
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -0,0 +1,52 @@
# \u4EE5\u4E0B\u5185\u5BB9\u590D\u5236\u5230 nacos \u914D\u7F6E\u6587\u4EF6\u4E2D
# Copy the following to the nacos configuration file
spring.dynamic.thread-pool.tomcat.core-pool-size=64
spring.dynamic.thread-pool.tomcat.maximum-pool-size=128
spring.dynamic.thread-pool.tomcat.keep-alive-time=1000
spring.dynamic.thread-pool.tomcat.enable=true
spring.dynamic.thread-pool.default-executor.core-pool-size=1
spring.dynamic.thread-pool.default-executor.maximum-pool-size=2
spring.dynamic.thread-pool.default-executor.blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.default-executor.execute-time-out=100
spring.dynamic.thread-pool.default-executor.keep-alive-time=6691
spring.dynamic.thread-pool.default-executor.queue-capacity=1
spring.dynamic.thread-pool.default-executor.rejected-handler=AbortPolicy
spring.dynamic.thread-pool.default-executor.active-alarm=90
spring.dynamic.thread-pool.default-executor.capacity-alarm=85
spring.dynamic.thread-pool.default-executor.alarm=true
spring.dynamic.thread-pool.default-executor.allow-core-thread-time-out=true
spring.dynamic.thread-pool.default-executor.notify.interval=5
spring.dynamic.thread-pool.default-executor.notify.receives=chen.ma
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ec3be378-6c99-45d2-a147-b400c7e94a08
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -6,7 +6,7 @@ management.server.port=29999
management.endpoints.web.exposure.include=* management.endpoints.web.exposure.include=*
spring.profiles.active=dev spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example spring.application.name=hippo4j-config-nacos-spring-boot-starter-example
spring.cloud.nacos.config.password=nacos spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.server-addr=127.0.0.1:8848
@ -17,33 +17,51 @@ spring.cloud.nacos.config.extension-configs[0].refresh=true
spring.dynamic.thread-pool.enable=true spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=true spring.dynamic.thread-pool.banner=true
spring.dynamic.thread-pool.collect=true
spring.dynamic.thread-pool.collect-type=micrometer
spring.dynamic.thread-pool.check-state-interval=5 spring.dynamic.thread-pool.check-state-interval=5
spring.dynamic.thread-pool.monitor.enable=true
spring.dynamic.thread-pool.monitor.collect-types=micrometer
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ac0426a5-c712-474c-9bff-72b8b8f5caff spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff
spring.dynamic.thread-pool.notify-platforms[1].platform=DING spring.dynamic.thread-pool.notify-platforms[1].platform=DING
spring.dynamic.thread-pool.notify-platforms[1].secret-key=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55 spring.dynamic.thread-pool.notify-platforms[1].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
spring.dynamic.thread-pool.notify-platforms[2].platform=LARK spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
spring.dynamic.thread-pool.notify-platforms[2].secret-key=2cbf2808-3839-4c26-a04d-fd201dd51f9e spring.dynamic.thread-pool.notify-platforms[2].token=2cbf2808-3839-4c26-a04d-fd201dd51f9e
spring.dynamic.thread-pool.nacos.data-id=hippo4j-nacos.yaml spring.dynamic.thread-pool.nacos.data-id=hippo4j-nacos.yaml
spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP
spring.dynamic.thread-pool.config-file-type=yml spring.dynamic.thread-pool.config-file-type=yml
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=1 spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].maximum-pool-size=1 spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].queue-capacity=1 spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].blocking-queue=LinkedBlockingQueue spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].execute-time-out=1000 spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691 spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].alarm=true spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80 spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80 spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8 spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -0,0 +1,52 @@
# \u4EE5\u4E0B\u5185\u5BB9\u590D\u5236\u5230 nacos \u914D\u7F6E\u6587\u4EF6\u4E2D
# Copy the following to the nacos configuration file
spring.dynamic.thread-pool.tomcat.core-pool-size=64
spring.dynamic.thread-pool.tomcat.maximum-pool-size=128
spring.dynamic.thread-pool.tomcat.keep-alive-time=1000
spring.dynamic.thread-pool.tomcat.enable=true
spring.dynamic.thread-pool.default-executor.core-pool-size=1
spring.dynamic.thread-pool.default-executor.maximum-pool-size=2
spring.dynamic.thread-pool.default-executor.blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.default-executor.execute-time-out=100
spring.dynamic.thread-pool.default-executor.keep-alive-time=6691
spring.dynamic.thread-pool.default-executor.queue-capacity=1
spring.dynamic.thread-pool.default-executor.rejected-handler=AbortPolicy
spring.dynamic.thread-pool.default-executor.active-alarm=90
spring.dynamic.thread-pool.default-executor.capacity-alarm=85
spring.dynamic.thread-pool.default-executor.alarm=true
spring.dynamic.thread-pool.default-executor.allow-core-thread-time-out=true
spring.dynamic.thread-pool.default-executor.notify.interval=5
spring.dynamic.thread-pool.default-executor.notify.receives=chen.ma
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ec3be378-6c99-45d2-a147-b400c7e94a08
spring.dynamic.thread-pool.executors[0].thread-pool-id=message-consume
spring.dynamic.thread-pool.executors[0].thread-name-prefix=message-consume
spring.dynamic.thread-pool.executors[0].core-pool-size=2
spring.dynamic.thread-pool.executors[0].maximum-pool-size=4
spring.dynamic.thread-pool.executors[0].queue-capacity=1024
spring.dynamic.thread-pool.executors[0].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].execute-time-out=800
spring.dynamic.thread-pool.executors[0].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[0].keep-alive-time=6691
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[0].alarm=true
spring.dynamic.thread-pool.executors[0].active-alarm=80
spring.dynamic.thread-pool.executors[0].capacity-alarm=80
spring.dynamic.thread-pool.executors[0].notify.interval=8
spring.dynamic.thread-pool.executors[0].notify.receives=chen.ma
spring.dynamic.thread-pool.executors[1].thread-pool-id=message-produce
spring.dynamic.thread-pool.executors[1].thread-name-prefix=message-produce
spring.dynamic.thread-pool.executors[1].core-pool-size=2
spring.dynamic.thread-pool.executors[1].maximum-pool-size=4
spring.dynamic.thread-pool.executors[1].queue-capacity=1024
spring.dynamic.thread-pool.executors[1].blocking-queue=ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].execute-time-out=800
spring.dynamic.thread-pool.executors[1].rejected-handler=AbortPolicy
spring.dynamic.thread-pool.executors[1].keep-alive-time=6691
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out=true
spring.dynamic.thread-pool.executors[1].alarm=true
spring.dynamic.thread-pool.executors[1].active-alarm=80
spring.dynamic.thread-pool.executors[1].capacity-alarm=80
spring.dynamic.thread-pool.executors[1].notify.interval=8
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma

@ -18,7 +18,6 @@
package cn.hippo4j.example.core.inittest; package cn.hippo4j.example.core.inittest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -29,8 +28,6 @@ import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static cn.hippo4j.common.constant.Constants.EXECUTE_TIMEOUT_TRACE;
/** /**
* Run state handler test. * Run state handler test.
*/ */
@ -81,7 +78,7 @@ public class RunStateHandlerTest {
/** /**
* When the execution of the thread pool task times out, the Trace flag is put into the MDC, and it is printed out when an alarm occurs. * When the execution of the thread pool task times out, the Trace flag is put into the MDC, and it is printed out when an alarm occurs.
*/ */
MDC.put(EXECUTE_TIMEOUT_TRACE, "39948722194639841.251.16612352194691531"); // MDC.put(EXECUTE_TIMEOUT_TRACE, "39948722194639841.251.16612352194691531");
try { try {
Thread.sleep(5000); Thread.sleep(5000);
} catch (InterruptedException e) { } catch (InterruptedException e) {

@ -3,7 +3,7 @@ server.port=8088
server.servlet.context-path=/example server.servlet.context-path=/example
spring.profiles.active=dev spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example spring.application.name=hippo4j-spring-boot-starter-es-monitor-example
es.thread-pool-state.host = ip1:port,ip2:port es.thread-pool-state.host = ip1:port,ip2:port
es.thread-pool-state.scheme = http es.thread-pool-state.scheme = http
@ -14,8 +14,11 @@ es.thread-pool-state.index.name = thread-pool-state
spring.dynamic.thread-pool.item-id=test spring.dynamic.thread-pool.item-id=test
spring.dynamic.thread-pool.enable=true spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=false spring.dynamic.thread-pool.banner=false
spring.dynamic.thread-pool.collect=true spring.dynamic.thread-pool.monitor.enable=true
spring.dynamic.thread-pool.collect-type=es spring.dynamic.thread-pool.monitor.collect-types=elasticsearch
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000
spring.dynamic.thread-pool.notify-platforms[0].platform=DING spring.dynamic.thread-pool.notify-platforms[0].platform=DING
spring.dynamic.thread-pool.notify-platforms[0].token=xxx spring.dynamic.thread-pool.notify-platforms[0].token=xxx
spring.dynamic.thread-pool.notify-platforms[0].secret=xxx spring.dynamic.thread-pool.notify-platforms[0].secret=xxx

@ -7,7 +7,7 @@ management.server.port=29901
management.endpoints.web.exposure.include=* management.endpoints.web.exposure.include=*
spring.profiles.active=dev spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example spring.application.name=hippo4j-spring-boot-starter-example
spring.dynamic.thread-pool.server-addr=http://localhost:6691 spring.dynamic.thread-pool.server-addr=http://localhost:6691
### Use netty to report thread pool monitoring data. The default is http. ### Use netty to report thread pool monitoring data. The default is http.
@ -19,4 +19,8 @@ spring.dynamic.thread-pool.username=admin
spring.dynamic.thread-pool.password=123456 spring.dynamic.thread-pool.password=123456
# Enable server and micrometer monitoring at the same time # Enable server and micrometer monitoring at the same time
spring.dynamic.thread-pool.collect-type=server,micrometer spring.dynamic.thread-pool.monitor.enable=true
spring.dynamic.thread-pool.monitor.collect-types=server,micrometer
spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
spring.dynamic.thread-pool.monitor.initial-delay=10000
spring.dynamic.thread-pool.monitor.collect-interval=5000

@ -30,7 +30,7 @@ public interface NotifyConfigBuilder {
/** /**
* Build notify. * Build notify.
* *
* @return * @return notify info
*/ */
Map<String, List<NotifyConfigDTO>> buildNotify(); Map<String, List<NotifyConfigDTO>> buildNotify();
} }

@ -60,8 +60,8 @@ public class DingSendMessageHandler extends AbstractRobotSendMessageHandler {
RobotMessageActualContent robotMessageActualContent = RobotMessageActualContent.builder() RobotMessageActualContent robotMessageActualContent = RobotMessageActualContent.builder()
.receiveSeparator(", @") .receiveSeparator(", @")
.changeSeparator(" -> ") .changeSeparator(" -> ")
.replaceTxt(DING_ALARM_TIMOUT_REPLACE_TXT) .replaceTxt(DING_ALARM_TIMEOUT_REPLACE_TXT)
.traceReplaceTxt(DING_ALARM_TIMOUT_TRACE_REPLACE_TXT) .traceReplaceTxt(DING_ALARM_TIMEOUT_TRACE_REPLACE_TXT)
.alarmMessageContent(Singleton.get(dingAlarmTxtKey, () -> FileUtil.readUtf8String(dingAlarmTxtKey))) .alarmMessageContent(Singleton.get(dingAlarmTxtKey, () -> FileUtil.readUtf8String(dingAlarmTxtKey)))
.configMessageContent(Singleton.get(dingConfigTxtKey, () -> FileUtil.readUtf8String(dingConfigTxtKey))) .configMessageContent(Singleton.get(dingConfigTxtKey, () -> FileUtil.readUtf8String(dingConfigTxtKey)))
.build(); .build();

@ -55,66 +55,46 @@ public class LarkSendMessageHandler implements SendMessageHandler<AlarmNotifyReq
@SneakyThrows @SneakyThrows
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) { public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
String afterReceives = getReceives(notifyConfig.getReceives()); String afterReceives = getReceives(notifyConfig.getReceives());
String larkAlarmTimoutReplaceTxt; String larkAlarmTimeoutReplaceTxt;
String larkAlarmTxtKey = "message/robot/dynamic-thread-pool/lark-alarm.json"; String larkAlarmTxtKey = "message/robot/dynamic-thread-pool/lark-alarm.json";
String larkAlarmTxt = Singleton.get(larkAlarmTxtKey, () -> FileUtil.readUtf8String(larkAlarmTxtKey)); String larkAlarmTxt = Singleton.get(larkAlarmTxtKey, () -> FileUtil.readUtf8String(larkAlarmTxtKey));
String larkAlarmTimoutReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json"; String larkAlarmTimeoutReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json";
String larkAlarmTimoutReplaceJson = Singleton.get(larkAlarmTimoutReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutReplaceJsonKey)); String larkAlarmTimeoutReplaceJson = Singleton.get(larkAlarmTimeoutReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimeoutReplaceJsonKey));
if (Objects.equals(alarmNotifyRequest.getNotifyTypeEnum(), NotifyTypeEnum.TIMEOUT)) { if (Objects.equals(alarmNotifyRequest.getNotifyTypeEnum(), NotifyTypeEnum.TIMEOUT)) {
String executeTimeoutTrace = alarmNotifyRequest.getExecuteTimeoutTrace(); String executeTimeoutTrace = alarmNotifyRequest.getExecuteTimeoutTrace();
String larkAlarmTimoutTraceReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json"; String larkAlarmTimoutTraceReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json";
String larkAlarmTimoutTraceReplaceJson = Singleton.get(larkAlarmTimoutTraceReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutTraceReplaceJsonKey)); String larkAlarmTimoutTraceReplaceJson = Singleton.get(larkAlarmTimoutTraceReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutTraceReplaceJsonKey));
if (StringUtil.isNotBlank(executeTimeoutTrace)) { if (StringUtil.isNotBlank(executeTimeoutTrace)) {
String larkAlarmTimoutTraceReplaceTxt = String.format(larkAlarmTimoutTraceReplaceJson, executeTimeoutTrace); String larkAlarmTimoutTraceReplaceTxt = String.format(larkAlarmTimoutTraceReplaceJson, executeTimeoutTrace);
larkAlarmTimoutReplaceTxt = StringUtil.replace(larkAlarmTimoutReplaceJson, larkAlarmTimoutTraceReplaceJson, larkAlarmTimoutTraceReplaceTxt); larkAlarmTimeoutReplaceTxt = StringUtil.replace(larkAlarmTimeoutReplaceJson, larkAlarmTimoutTraceReplaceJson, larkAlarmTimoutTraceReplaceTxt);
} else { } else {
larkAlarmTimoutReplaceTxt = StringUtil.replace(larkAlarmTimoutReplaceJson, larkAlarmTimoutTraceReplaceJson, ""); larkAlarmTimeoutReplaceTxt = StringUtil.replace(larkAlarmTimeoutReplaceJson, larkAlarmTimoutTraceReplaceJson, "");
} }
larkAlarmTimoutReplaceTxt = String.format(larkAlarmTimoutReplaceTxt, alarmNotifyRequest.getExecuteTime(), alarmNotifyRequest.getExecuteTimeOut()); larkAlarmTimeoutReplaceTxt = String.format(larkAlarmTimeoutReplaceTxt, alarmNotifyRequest.getExecuteTime(), alarmNotifyRequest.getExecuteTimeOut());
larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimoutReplaceJson, larkAlarmTimoutReplaceTxt); larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimeoutReplaceJson, larkAlarmTimeoutReplaceTxt);
} else { } else {
larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimoutReplaceJson, ""); larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimeoutReplaceJson, "");
} }
String text = String.format(larkAlarmTxt, String text = String.format(larkAlarmTxt,
// 环境
alarmNotifyRequest.getActive(), alarmNotifyRequest.getActive(),
// 报警类型
alarmNotifyRequest.getNotifyTypeEnum(), alarmNotifyRequest.getNotifyTypeEnum(),
// 线程池ID
alarmNotifyRequest.getThreadPoolId(), alarmNotifyRequest.getThreadPoolId(),
// 应用名称
alarmNotifyRequest.getAppName(), alarmNotifyRequest.getAppName(),
// 实例信息
alarmNotifyRequest.getIdentify(), alarmNotifyRequest.getIdentify(),
// 核心线程数
alarmNotifyRequest.getCorePoolSize(), alarmNotifyRequest.getCorePoolSize(),
// 最大线程数
alarmNotifyRequest.getMaximumPoolSize(), alarmNotifyRequest.getMaximumPoolSize(),
// 当前线程数
alarmNotifyRequest.getPoolSize(), alarmNotifyRequest.getPoolSize(),
// 活跃线程数
alarmNotifyRequest.getActiveCount(), alarmNotifyRequest.getActiveCount(),
// 最大任务数
alarmNotifyRequest.getLargestPoolSize(), alarmNotifyRequest.getLargestPoolSize(),
// 线程池任务总量
alarmNotifyRequest.getCompletedTaskCount(), alarmNotifyRequest.getCompletedTaskCount(),
// 队列类型名称
alarmNotifyRequest.getQueueName(), alarmNotifyRequest.getQueueName(),
// 队列容量
alarmNotifyRequest.getCapacity(), alarmNotifyRequest.getCapacity(),
// 队列元素个数
alarmNotifyRequest.getQueueSize(), alarmNotifyRequest.getQueueSize(),
// 队列剩余个数
alarmNotifyRequest.getRemainingCapacity(), alarmNotifyRequest.getRemainingCapacity(),
// 拒绝策略名称
alarmNotifyRequest.getRejectedExecutionHandlerName(), alarmNotifyRequest.getRejectedExecutionHandlerName(),
// 拒绝策略次数
alarmNotifyRequest.getRejectCountNum(), alarmNotifyRequest.getRejectCountNum(),
// 告警手机号
afterReceives, afterReceives,
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
// 报警频率
notifyConfig.getInterval()); notifyConfig.getInterval());
execute(notifyConfig.getSecretKey(), text); execute(notifyConfig.getSecretKey(), text);
} }
@ -127,34 +107,20 @@ public class LarkSendMessageHandler implements SendMessageHandler<AlarmNotifyReq
String larkNoticeJsonKey = "message/robot/dynamic-thread-pool/lark-config.json"; String larkNoticeJsonKey = "message/robot/dynamic-thread-pool/lark-config.json";
String larkNoticeJson = Singleton.get(larkNoticeJsonKey, () -> FileUtil.readUtf8String(larkNoticeJsonKey)); String larkNoticeJson = Singleton.get(larkNoticeJsonKey, () -> FileUtil.readUtf8String(larkNoticeJsonKey));
String text = String.format(larkNoticeJson, String text = String.format(larkNoticeJson,
// 环境
changeParameterNotifyRequest.getActive(), changeParameterNotifyRequest.getActive(),
// 线程池名称
threadPoolId, threadPoolId,
// 应用名称
changeParameterNotifyRequest.getAppName(), changeParameterNotifyRequest.getAppName(),
// 实例信息
changeParameterNotifyRequest.getIdentify(), changeParameterNotifyRequest.getIdentify(),
// 核心线程数
changeParameterNotifyRequest.getBeforeCorePoolSize() + " ➲ " + changeParameterNotifyRequest.getNowCorePoolSize(), changeParameterNotifyRequest.getBeforeCorePoolSize() + " ➲ " + changeParameterNotifyRequest.getNowCorePoolSize(),
// 最大线程数
changeParameterNotifyRequest.getBeforeMaximumPoolSize() + " ➲ " + changeParameterNotifyRequest.getNowMaximumPoolSize(), changeParameterNotifyRequest.getBeforeMaximumPoolSize() + " ➲ " + changeParameterNotifyRequest.getNowMaximumPoolSize(),
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(), changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(), changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(), changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
changeParameterNotifyRequest.getBeforeQueueCapacity() + " ➲ " + changeParameterNotifyRequest.getNowQueueCapacity(), changeParameterNotifyRequest.getBeforeQueueCapacity() + " ➲ " + changeParameterNotifyRequest.getNowQueueCapacity(),
// 执行超时时间
changeParameterNotifyRequest.getBeforeExecuteTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowExecuteTimeOut(), changeParameterNotifyRequest.getBeforeExecuteTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowExecuteTimeOut(),
// 拒绝策略
changeParameterNotifyRequest.getBeforeRejectedName(), changeParameterNotifyRequest.getBeforeRejectedName(),
changeParameterNotifyRequest.getNowRejectedName(), changeParameterNotifyRequest.getNowRejectedName(),
// 告警手机号
afterReceives, afterReceives,
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
execute(notifyConfig.getSecretKey(), text); execute(notifyConfig.getSecretKey(), text);
} }

@ -37,22 +37,22 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
/** /**
* Build message actual content. * Build message actual content.
* *
* @return * @return robot message actual content
*/ */
protected abstract RobotMessageActualContent buildMessageActualContent(); protected abstract RobotMessageActualContent buildMessageActualContent();
/** /**
* Execute. * Execute.
* *
* @param robotMessageExecuteDTO * @param robotMessageExecuteDTO robot message execute dto
*/ */
protected abstract void execute(RobotMessageExecuteDTO robotMessageExecuteDTO); protected abstract void execute(RobotMessageExecuteDTO robotMessageExecuteDTO);
/** /**
* Send alarm message. * Send alarm message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param alarmNotifyRequest * @param alarmNotifyRequest alarm notify request
*/ */
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) { public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
RobotMessageActualContent robotMessageActualContent = buildMessageActualContent(); RobotMessageActualContent robotMessageActualContent = buildMessageActualContent();
@ -75,45 +75,25 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
alarmContentTxt = StringUtil.replace(alarmContentTxt, "${timout-content}", replaceTxt); alarmContentTxt = StringUtil.replace(alarmContentTxt, "${timout-content}", replaceTxt);
String text = String.format( String text = String.format(
alarmContentTxt, alarmContentTxt,
// 环境
alarmNotifyRequest.getActive(), alarmNotifyRequest.getActive(),
// 报警类型
alarmNotifyRequest.getNotifyTypeEnum(), alarmNotifyRequest.getNotifyTypeEnum(),
// 线程池ID
alarmNotifyRequest.getThreadPoolId(), alarmNotifyRequest.getThreadPoolId(),
// 应用名称
alarmNotifyRequest.getAppName(), alarmNotifyRequest.getAppName(),
// 实例信息
alarmNotifyRequest.getIdentify(), alarmNotifyRequest.getIdentify(),
// 核心线程数
alarmNotifyRequest.getCorePoolSize(), alarmNotifyRequest.getCorePoolSize(),
// 最大线程数
alarmNotifyRequest.getMaximumPoolSize(), alarmNotifyRequest.getMaximumPoolSize(),
// 当前线程数
alarmNotifyRequest.getPoolSize(), alarmNotifyRequest.getPoolSize(),
// 活跃线程数
alarmNotifyRequest.getActiveCount(), alarmNotifyRequest.getActiveCount(),
// 最大任务数
alarmNotifyRequest.getLargestPoolSize(), alarmNotifyRequest.getLargestPoolSize(),
// 线程池任务总量
alarmNotifyRequest.getCompletedTaskCount(), alarmNotifyRequest.getCompletedTaskCount(),
// 队列类型名称
alarmNotifyRequest.getQueueName(), alarmNotifyRequest.getQueueName(),
// 队列容量
alarmNotifyRequest.getCapacity(), alarmNotifyRequest.getCapacity(),
// 队列元素个数
alarmNotifyRequest.getQueueSize(), alarmNotifyRequest.getQueueSize(),
// 队列剩余个数
alarmNotifyRequest.getRemainingCapacity(), alarmNotifyRequest.getRemainingCapacity(),
// 拒绝策略名称
alarmNotifyRequest.getRejectedExecutionHandlerName(), alarmNotifyRequest.getRejectedExecutionHandlerName(),
// 拒绝策略次数
alarmNotifyRequest.getRejectCountNum(), alarmNotifyRequest.getRejectCountNum(),
// 告警手机号
Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")), Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")),
// 报警频率
notifyConfig.getInterval(), notifyConfig.getInterval(),
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build()); execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build());
} }
@ -121,8 +101,8 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
/** /**
* Send change message. * Send change message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param changeParameterNotifyRequest * @param changeParameterNotifyRequest change parameter notify request
*/ */
public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) { public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
RobotMessageActualContent robotMessageActualContent = buildMessageActualContent(); RobotMessageActualContent robotMessageActualContent = buildMessageActualContent();
@ -130,34 +110,20 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
String changeSeparator = robotMessageActualContent.getChangeSeparator(); String changeSeparator = robotMessageActualContent.getChangeSeparator();
String text = String.format( String text = String.format(
robotMessageActualContent.getConfigMessageContent(), robotMessageActualContent.getConfigMessageContent(),
// 环境
changeParameterNotifyRequest.getActive(), changeParameterNotifyRequest.getActive(),
// 线程池名称
threadPoolId, threadPoolId,
// 应用名称
changeParameterNotifyRequest.getAppName(), changeParameterNotifyRequest.getAppName(),
// 实例信息
changeParameterNotifyRequest.getIdentify(), changeParameterNotifyRequest.getIdentify(),
// 核心线程数
changeParameterNotifyRequest.getBeforeCorePoolSize() + changeSeparator + changeParameterNotifyRequest.getNowCorePoolSize(), changeParameterNotifyRequest.getBeforeCorePoolSize() + changeSeparator + changeParameterNotifyRequest.getNowCorePoolSize(),
// 最大线程数
changeParameterNotifyRequest.getBeforeMaximumPoolSize() + changeSeparator + changeParameterNotifyRequest.getNowMaximumPoolSize(), changeParameterNotifyRequest.getBeforeMaximumPoolSize() + changeSeparator + changeParameterNotifyRequest.getNowMaximumPoolSize(),
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(), changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + changeSeparator + changeParameterNotifyRequest.getNowKeepAliveTime(), changeParameterNotifyRequest.getBeforeKeepAliveTime() + changeSeparator + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 执行超时时间
changeParameterNotifyRequest.getBeforeExecuteTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowExecuteTimeOut(), changeParameterNotifyRequest.getBeforeExecuteTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowExecuteTimeOut(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(), changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
changeParameterNotifyRequest.getBeforeQueueCapacity() + changeSeparator + changeParameterNotifyRequest.getNowQueueCapacity(), changeParameterNotifyRequest.getBeforeQueueCapacity() + changeSeparator + changeParameterNotifyRequest.getNowQueueCapacity(),
// 拒绝策略
changeParameterNotifyRequest.getBeforeRejectedName(), changeParameterNotifyRequest.getBeforeRejectedName(),
changeParameterNotifyRequest.getNowRejectedName(), changeParameterNotifyRequest.getNowRejectedName(),
// 告警手机号
Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")), Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")),
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build()); execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build());
} }

@ -40,14 +40,14 @@ public class DingAlarmConstants {
/** /**
* Trace info * Trace info
*/ */
public static final String DING_ALARM_TIMOUT_TRACE_REPLACE_TXT = "<font color=#708090 size=2>链路信息:%s</font> \n\n "; public static final String DING_ALARM_TIMEOUT_TRACE_REPLACE_TXT = "<font color=#708090 size=2>链路信息:%s</font> \n\n ";
/** /**
* Replace task timeout template * Replace task timeout template
*/ */
public static final String DING_ALARM_TIMOUT_REPLACE_TXT = public static final String DING_ALARM_TIMEOUT_REPLACE_TXT =
"<font color=#708090 size=2>任务执行时间:%d / ms </font> \n\n " + "<font color=#708090 size=2>任务执行时间:%d / ms </font> \n\n " +
"<font color=#708090 size=2>超时时间:%d / ms</font> \n\n " + "<font color=#708090 size=2>超时时间:%d / ms</font> \n\n " +
DING_ALARM_TIMOUT_TRACE_REPLACE_TXT + DING_ALARM_TIMEOUT_TRACE_REPLACE_TXT +
" --- \n\n "; " --- \n\n ";
} }

@ -17,12 +17,6 @@
package cn.hippo4j.message.service; package cn.hippo4j.message.service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import cn.hippo4j.common.constant.Constants; import cn.hippo4j.common.constant.Constants;
import cn.hippo4j.common.toolkit.IdUtil; import cn.hippo4j.common.toolkit.IdUtil;
import cn.hippo4j.common.toolkit.StringUtil; import cn.hippo4j.common.toolkit.StringUtil;
@ -30,6 +24,12 @@ import cn.hippo4j.message.dto.AlarmControlDTO;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/** /**
* Alarm control assembly. * Alarm control assembly.
*/ */
@ -42,8 +42,8 @@ public class AlarmControlHandler {
/** /**
* Control message push alarm frequency. * Control message push alarm frequency.
* *
* @param alarmControl * @param alarmControl alarm control
* @return * @return is it possible to send
*/ */
public boolean isSendAlarm(AlarmControlDTO alarmControl) { public boolean isSendAlarm(AlarmControlDTO alarmControl) {
String threadPoolKey = alarmControl.buildPk(); String threadPoolKey = alarmControl.buildPk();
@ -72,9 +72,9 @@ public class AlarmControlHandler {
/** /**
* Init cache and lock. * Init cache and lock.
* *
* @param threadPoolId * @param threadPoolId thread-pool id
* @param platform * @param platform platform
* @param interval * @param interval interval
*/ */
public void initCacheAndLock(String threadPoolId, String platform, Integer interval) { public void initCacheAndLock(String threadPoolId, String platform, Integer interval) {
String threadPoolKey = threadPoolId + Constants.GROUP_KEY_DELIMITER + platform; String threadPoolKey = threadPoolId + Constants.GROUP_KEY_DELIMITER + platform;

@ -17,9 +17,9 @@
package cn.hippo4j.message.service; package cn.hippo4j.message.service;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.toolkit.CollectionUtil; import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.message.api.NotifyConfigBuilder; import cn.hippo4j.message.api.NotifyConfigBuilder;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.message.dto.AlarmControlDTO; import cn.hippo4j.message.dto.AlarmControlDTO;
import cn.hippo4j.message.dto.NotifyConfigDTO; import cn.hippo4j.message.dto.NotifyConfigDTO;
import cn.hippo4j.message.enums.NotifyTypeEnum; import cn.hippo4j.message.enums.NotifyTypeEnum;
@ -28,7 +28,7 @@ import cn.hippo4j.message.request.ChangeParameterNotifyRequest;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner; import org.springframework.beans.factory.InitializingBean;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -39,7 +39,7 @@ import java.util.Map;
*/ */
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService, CommandLineRunner { public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService, InitializingBean {
private final NotifyConfigBuilder notifyConfigBuilder; private final NotifyConfigBuilder notifyConfigBuilder;
@ -109,9 +109,9 @@ public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService,
/** /**
* Is send alarm. * Is send alarm.
* *
* @param threadPoolId * @param threadPoolId thread-pool id
* @param platform * @param platform platform
* @param typeEnum * @param typeEnum type enum
* @return * @return
*/ */
private boolean isSendAlarm(String threadPoolId, String platform, NotifyTypeEnum typeEnum) { private boolean isSendAlarm(String threadPoolId, String platform, NotifyTypeEnum typeEnum) {
@ -123,21 +123,21 @@ public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService,
return alarmControlHandler.isSendAlarm(alarmControl); return alarmControlHandler.isSendAlarm(alarmControl);
} }
@Override
public void run(String... args) throws Exception {
Map<String, SendMessageHandler> sendMessageHandlerMap =
ApplicationContextHolder.getBeansOfType(SendMessageHandler.class);
sendMessageHandlerMap.values().forEach(each -> sendMessageHandlers.put(each.getType(), each));
Map<String, List<NotifyConfigDTO>> buildNotify = notifyConfigBuilder.buildNotify();
notifyConfigs.putAll(buildNotify);
}
/** /**
* Put platform. * Put platform.
* *
* @param notifyConfigs * @param notifyConfigs notify configs
*/ */
public synchronized void putPlatform(Map<String, List<NotifyConfigDTO>> notifyConfigs) { public synchronized void putPlatform(Map<String, List<NotifyConfigDTO>> notifyConfigs) {
this.notifyConfigs.putAll(notifyConfigs); this.notifyConfigs.putAll(notifyConfigs);
} }
@Override
public void afterPropertiesSet() throws Exception {
Map<String, SendMessageHandler> sendMessageHandlerMap =
ApplicationContextHolder.getBeansOfType(SendMessageHandler.class);
sendMessageHandlerMap.values().forEach(each -> sendMessageHandlers.put(each.getType(), each));
Map<String, List<NotifyConfigDTO>> buildNotify = notifyConfigBuilder.buildNotify();
notifyConfigs.putAll(buildNotify);
}
} }

@ -29,15 +29,15 @@ public interface Hippo4jSendMessageService {
/** /**
* Send dynamic thread pool alert notifications. * Send dynamic thread pool alert notifications.
* *
* @param typeEnum * @param typeEnum type enum
* @param alarmNotifyRequest * @param alarmNotifyRequest alarm notify request
*/ */
void sendAlarmMessage(NotifyTypeEnum typeEnum, AlarmNotifyRequest alarmNotifyRequest); void sendAlarmMessage(NotifyTypeEnum typeEnum, AlarmNotifyRequest alarmNotifyRequest);
/** /**
* Send dynamic thread pool parameter change notification. * Send dynamic thread pool parameter change notification.
* *
* @param changeParameterNotifyRequest * @param changeParameterNotifyRequest change parameter notify request
*/ */
void sendChangeMessage(ChangeParameterNotifyRequest changeParameterNotifyRequest); void sendChangeMessage(ChangeParameterNotifyRequest changeParameterNotifyRequest);
} }

@ -26,25 +26,25 @@ import cn.hippo4j.message.request.base.NotifyRequest;
public interface SendMessageHandler<T extends NotifyRequest, R extends NotifyRequest> { public interface SendMessageHandler<T extends NotifyRequest, R extends NotifyRequest> {
/** /**
* Get type. * Get the message send type.
* *
* @return * @return message type
*/ */
String getType(); String getType();
/** /**
* Send alarm message. * Send alarm message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param alarmNotifyRequest * @param alarmNotifyRequest alarm notify request
*/ */
void sendAlarmMessage(NotifyConfigDTO notifyConfig, T alarmNotifyRequest); void sendAlarmMessage(NotifyConfigDTO notifyConfig, T alarmNotifyRequest);
/** /**
* Send change message. * Send change message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param changeParameterNotifyRequest * @param changeParameterNotifyRequest change parameter notify request
*/ */
void sendChangeMessage(NotifyConfigDTO notifyConfig, R changeParameterNotifyRequest); void sendChangeMessage(NotifyConfigDTO notifyConfig, R changeParameterNotifyRequest);
} }

@ -14,8 +14,8 @@
"content": "** 超时时间:** %s", "content": "** 超时时间:** %s",
"tag": "lark_md" "tag": "lark_md"
} }
}, }
{ ,{
"is_short": true, "is_short": true,
"text": { "text": {
"content": "** 链路信息:** %s", "content": "** 链路信息:** %s",

@ -1,5 +1,5 @@
{ ,{
"is_short": true, "is_short": true,
"text": { "text": {
"content": "** 链路信息:** %s", "content": "** 链路信息:** %s",

@ -142,8 +142,8 @@
"content": "** 超时时间:** %s", "content": "** 超时时间:** %s",
"tag": "lark_md" "tag": "lark_md"
} }
}, }
{ ,{
"is_short": true, "is_short": true,
"text": { "text": {
"content": "** 链路信息:** %s", "content": "** 链路信息:** %s",

@ -22,7 +22,7 @@ import cn.hippo4j.message.enums.NotifyTypeEnum;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
public class AlarmControlHandlerTest { public final class AlarmControlHandlerTest {
@Test @Test
public void assertIsNotSendAlarm() { public void assertIsNotSendAlarm() {

@ -13,6 +13,17 @@
<dependency> <dependency>
<groupId>cn.hippo4j</groupId> <groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-core</artifactId> <artifactId>hippo4j-core</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-adapter-web</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-adapter-base</artifactId>
<version>${revision}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.base;
import cn.hippo4j.adapter.base.ThreadPoolAdapter;
import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.common.config.ApplicationContextHolder;
import java.util.Map;
/**
* Abstract adapter thread-pool monitor.
*/
public abstract class AbstractAdapterThreadPoolMonitor implements AdapterThreadPoolMonitor {
/**
* Execute collection thread pool running data.
*
* @param threadPoolAdapterState thread-pool adapter state
*/
protected abstract void execute(ThreadPoolAdapterState threadPoolAdapterState);
@Override
public void collect() {
Map<String, ThreadPoolAdapter> threadPoolAdapterMap = ApplicationContextHolder.getBeansOfType(ThreadPoolAdapter.class);
threadPoolAdapterMap.forEach((beanName, bean) -> bean.getThreadPoolStates().forEach(each -> execute(each)));
}
}

@ -20,24 +20,24 @@ package cn.hippo4j.monitor.base;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage; import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler; import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import lombok.RequiredArgsConstructor;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
* Abstract dynamic thread-pool monitor. * Abstract dynamic thread-pool monitor.
*/ */
@RequiredArgsConstructor
public abstract class AbstractDynamicThreadPoolMonitor implements DynamicThreadPoolMonitor { public abstract class AbstractDynamicThreadPoolMonitor implements DynamicThreadPoolMonitor {
private final ThreadPoolRunStateHandler threadPoolRunStateHandler; @Resource
private ThreadPoolRunStateHandler threadPoolRunStateHandler;
/** /**
* Execute collection thread pool running data. * Execute collection thread pool running data.
* *
* @param poolRunStateInfo * @param dynamicThreadPoolRunStateInfo dynamic thread-pool run state info
*/ */
protected abstract void execute(ThreadPoolRunStateInfo poolRunStateInfo); protected abstract void execute(ThreadPoolRunStateInfo dynamicThreadPoolRunStateInfo);
@Override @Override
public void collect() { public void collect() {

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.base;
import cn.hippo4j.adapter.web.WebThreadPoolService;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import javax.annotation.Resource;
/**
* Abstract web thread-pool monitor.
*/
public abstract class AbstractWebThreadPoolMonitor implements WebThreadPoolMonitor {
@Resource
private WebThreadPoolService webThreadPoolService;
/**
* Execute collection thread pool running data.
*
* @param webThreadPoolRunStateInfo web thread-pool run state info
*/
protected abstract void execute(ThreadPoolRunStateInfo webThreadPoolRunStateInfo);
@Override
public void collect() {
ThreadPoolRunStateInfo webThreadPoolRunStateInfo = webThreadPoolService.getWebRunStateInfo();
execute(webThreadPoolRunStateInfo);
}
}

@ -15,21 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.springboot.starter.monitor.es; package cn.hippo4j.monitor.base;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.es.EsMonitorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/** /**
* Elastic-search monitor auto configuration. * Adapter thread-pool monitor.
*/ */
@Configuration public interface AdapterThreadPoolMonitor extends ThreadPoolMonitor {
public class EsMonitorAutoConfiguration {
@Bean
public EsMonitorHandler esMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
return new EsMonitorHandler(threadPoolRunStateHandler);
}
} }

@ -15,20 +15,25 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.springboot.starter.config; package cn.hippo4j.monitor.base;
import cn.hippo4j.springboot.starter.remote.HttpAgent;
import cn.hippo4j.springboot.starter.remote.ServerHttpAgent;
import org.springframework.context.annotation.Bean;
/** /**
* Http client config. * Monitor thread-pool type enum.
*/ */
public class HttpClientConfiguration { public enum MonitorThreadPoolTypeEnum {
/**
* Dynamic thread-pool
*/
DYNAMIC,
/**
* Web thread-pool
*/
WEB,
@Bean /**
@SuppressWarnings("all") * Adapter thread-pool
public HttpAgent httpAgent(BootstrapProperties properties) { */
return new ServerHttpAgent(properties); ADAPTER
}
} }

@ -18,19 +18,19 @@
package cn.hippo4j.monitor.base; package cn.hippo4j.monitor.base;
/** /**
* Thread-pool monitor. * Thread-pool runtime monitor.
*/ */
public interface ThreadPoolMonitor { public interface ThreadPoolMonitor {
/** /**
* Get type. * Get thread-pool monitoring type.
* *
* @return * @return monitoring type
*/ */
String getType(); String getType();
/** /**
* Collect data. * Collect thread-pool runtime data.
*/ */
void collect(); void collect();
} }

@ -15,7 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.auth.secuity; package cn.hippo4j.monitor.base;
/**
* Web thread-pool monitor.
*/
public interface WebThreadPoolMonitor extends ThreadPoolMonitor {
public final class JwtTokenManagerTest {
} }

@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/**
* Adapter thread-pool elastic-search monitor handler.
*/
@Slf4j
public class AdapterThreadPoolElasticSearchMonitorHandler extends AbstractDynamicThreadPoolMonitor {
@Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
// TODO
}
@Override
public String getType() {
return MonitorTypeEnum.ELASTICSEARCH.name().toLowerCase();
}
}

@ -15,26 +15,25 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.monitor.es; package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.BeanUtil; import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.FileUtil; import cn.hippo4j.common.toolkit.FileUtil;
import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.es.model.EsThreadPoolRunStateInfo;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import cn.hippo4j.monitor.elasticsearch.model.ElasticSearchThreadPoolRunStateInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -47,20 +46,16 @@ import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* Elastic-search monitor handler. * Dynamic thread-pool elastic-search monitor handler.
*/ */
@Slf4j @Slf4j
public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor { public class DynamicThreadPoolElasticSearchMonitorHandler extends AbstractDynamicThreadPoolMonitor {
public EsMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
super(threadPoolRunStateHandler);
}
private AtomicBoolean isIndexExist = null; private AtomicBoolean isIndexExist = null;
@Override @Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
EsThreadPoolRunStateInfo esThreadPoolRunStateInfo = BeanUtil.convert(poolRunStateInfo, EsThreadPoolRunStateInfo.class); ElasticSearchThreadPoolRunStateInfo esThreadPoolRunStateInfo = BeanUtil.convert(poolRunStateInfo, ElasticSearchThreadPoolRunStateInfo.class);
Environment environment = ApplicationContextHolder.getInstance().getEnvironment(); Environment environment = ApplicationContextHolder.getInstance().getEnvironment();
String indexName = environment.getProperty("es.thread-pool-state.index.name", "thread-pool-state"); String indexName = environment.getProperty("es.thread-pool-state.index.name", "thread-pool-state");
String applicationName = environment.getProperty("spring.application.name", "application"); String applicationName = environment.getProperty("spring.application.name", "application");
@ -75,8 +70,8 @@ public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor {
this.log2Es(esThreadPoolRunStateInfo, indexName); this.log2Es(esThreadPoolRunStateInfo, indexName);
} }
public void log2Es(EsThreadPoolRunStateInfo esThreadPoolRunStateInfo, String indexName) { public void log2Es(ElasticSearchThreadPoolRunStateInfo esThreadPoolRunStateInfo, String indexName) {
RestHighLevelClient client = EsClientHolder.getClient(); RestHighLevelClient client = ElasticSearchClientHolder.getClient();
try { try {
IndexRequest request = new IndexRequest(indexName, "_doc"); IndexRequest request = new IndexRequest(indexName, "_doc");
request.id(esThreadPoolRunStateInfo.getId()); request.id(esThreadPoolRunStateInfo.getId());
@ -99,7 +94,7 @@ public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor {
boolean exists = false; boolean exists = false;
GetIndexRequest request = new GetIndexRequest(index); GetIndexRequest request = new GetIndexRequest(index);
try { try {
RestHighLevelClient client = EsClientHolder.getClient(); RestHighLevelClient client = ElasticSearchClientHolder.getClient();
exists = client.indices().exists(request, RequestOptions.DEFAULT); exists = client.indices().exists(request, RequestOptions.DEFAULT);
} catch (IOException e) { } catch (IOException e) {
log.error("check es index fail"); log.error("check es index fail");
@ -110,7 +105,7 @@ public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor {
} }
public void createIndex(String index, String type, String mapping, Integer shards, Integer replicas, String alias) { public void createIndex(String index, String type, String mapping, Integer shards, Integer replicas, String alias) {
RestHighLevelClient client = EsClientHolder.getClient(); RestHighLevelClient client = ElasticSearchClientHolder.getClient();
boolean acknowledged = false; boolean acknowledged = false;
CreateIndexRequest request = new CreateIndexRequest(index); CreateIndexRequest request = new CreateIndexRequest(index);
if (StringUtils.hasText(mapping)) { if (StringUtils.hasText(mapping)) {

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.monitor.es; package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.toolkit.StringUtil; import cn.hippo4j.common.toolkit.StringUtil;
@ -37,7 +37,7 @@ import java.util.List;
* Elastic-search client holder. * Elastic-search client holder.
*/ */
@Slf4j @Slf4j
public class EsClientHolder { public class ElasticSearchClientHolder {
private static String host; private static String host;

@ -15,21 +15,26 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.springboot.starter.monitor.local.log; package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.monitor.local.log.LocalLogMonitorHandler; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import org.springframework.context.annotation.Bean; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import org.springframework.context.annotation.Configuration; import lombok.extern.slf4j.Slf4j;
/** /**
* Local log monitor configuration. * Web thread-pool elastic-search monitor handler.
*/ */
@Configuration @Slf4j
public class LocalLogMonitorConfiguration { public class WebThreadPoolElasticSearchMonitorHandler extends AbstractDynamicThreadPoolMonitor {
@Bean @Override
public LocalLogMonitorHandler localLogMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
return new LocalLogMonitorHandler(threadPoolRunStateHandler); // TODO
}
@Override
public String getType() {
return MonitorTypeEnum.ELASTICSEARCH.name().toLowerCase();
} }
} }

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.monitor.es.model; package cn.hippo4j.monitor.elasticsearch.model;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import lombok.Getter; import lombok.Getter;
@ -26,7 +26,7 @@ import lombok.Setter;
*/ */
@Getter @Getter
@Setter @Setter
public class EsThreadPoolRunStateInfo extends ThreadPoolRunStateInfo { public class ElasticSearchThreadPoolRunStateInfo extends ThreadPoolRunStateInfo {
private String Id; private String Id;

@ -15,21 +15,27 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.springboot.starter.monitor.micrometer; package cn.hippo4j.monitor.local.log;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler; import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.monitor.micrometer.MicrometerMonitorHandler; import cn.hippo4j.common.toolkit.JSONUtil;
import org.springframework.context.annotation.Bean; import cn.hippo4j.monitor.base.AbstractAdapterThreadPoolMonitor;
import org.springframework.context.annotation.Configuration; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/** /**
* Micrometer monitor configuration. * Adapter thread-pool local log monitor handler.
*/ */
@Configuration @Slf4j
public class MicrometerMonitorConfiguration { public class AdapterThreadPoolLocalLogMonitorHandler extends AbstractAdapterThreadPoolMonitor {
@Bean @Override
public MicrometerMonitorHandler micrometerMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) { protected void execute(ThreadPoolAdapterState threadPoolAdapterState) {
return new MicrometerMonitorHandler(threadPoolRunStateHandler); log.info("{}", JSONUtil.toJSONString(threadPoolAdapterState));
}
@Override
public String getType() {
return MonitorTypeEnum.LOG.name().toLowerCase();
} }
} }

@ -19,20 +19,15 @@ package cn.hippo4j.monitor.local.log;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**
* Local log monitor handler. * Dynamic thread-pool local log monitor handler.
*/ */
@Slf4j @Slf4j
public class LocalLogMonitorHandler extends AbstractDynamicThreadPoolMonitor { public class DynamicThreadPoolLocalLogMonitorHandler extends AbstractDynamicThreadPoolMonitor {
public LocalLogMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
super(threadPoolRunStateHandler);
}
@Override @Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.local.log;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.monitor.base.AbstractWebThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/**
* Web thread-pool local log monitor handler.
*/
@Slf4j
public class WebThreadPoolLocalLogMonitorHandler extends AbstractWebThreadPoolMonitor {
@Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
log.info("{}", JSONUtil.toJSONString(poolRunStateInfo));
}
@Override
public String getType() {
return MonitorTypeEnum.LOG.name().toLowerCase();
}
}

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.micrometer;
import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.monitor.base.AbstractAdapterThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tag;
import org.springframework.core.env.Environment;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Adapter thread-pool micrometer monitor handler.
*/
public class AdapterThreadPoolMicrometerMonitorHandler extends AbstractAdapterThreadPoolMonitor {
private final static String METRIC_NAME_PREFIX = "adapter.thread-pool";
private final static String ADAPTER_THREAD_POOL_ID_TAG = METRIC_NAME_PREFIX + ".id";
private final static String APPLICATION_NAME_TAG = "application.name";
private final Map<String, ThreadPoolAdapterState> RUN_STATE_CACHE = new ConcurrentHashMap<>();
@Override
protected void execute(ThreadPoolAdapterState threadPoolAdapterState) {
ThreadPoolAdapterState stateInfo = RUN_STATE_CACHE.get(threadPoolAdapterState.getThreadPoolKey());
if (stateInfo == null) {
RUN_STATE_CACHE.put(threadPoolAdapterState.getThreadPoolKey(), threadPoolAdapterState);
} else {
BeanUtil.convert(threadPoolAdapterState, stateInfo);
}
Environment environment = ApplicationContextHolder.getInstance().getEnvironment();
String applicationName = environment.getProperty("spring.application.name", "application");
Iterable<Tag> tags = CollectionUtil.newArrayList(
Tag.of(ADAPTER_THREAD_POOL_ID_TAG, threadPoolAdapterState.getThreadPoolKey()),
Tag.of(APPLICATION_NAME_TAG, applicationName));
Metrics.gauge(metricName("core.size"), tags, threadPoolAdapterState, ThreadPoolAdapterState::getCoreSize);
Metrics.gauge(metricName("maximum.size"), tags, threadPoolAdapterState, ThreadPoolAdapterState::getMaximumSize);
Metrics.gauge(metricName("queue.capacity"), tags, threadPoolAdapterState, ThreadPoolAdapterState::getBlockingQueueCapacity);
}
private String metricName(String name) {
return String.join(".", METRIC_NAME_PREFIX, name);
}
@Override
public String getType() {
return MonitorTypeEnum.MICROMETER.name().toLowerCase();
}
}

@ -21,7 +21,6 @@ import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.BeanUtil; import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.CollectionUtil; import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.Metrics;
@ -32,9 +31,9 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* Micrometer monitor handler. * Dynamic thread-pool micrometer monitor handler.
*/ */
public class MicrometerMonitorHandler extends AbstractDynamicThreadPoolMonitor { public class DynamicThreadPoolMicrometerMonitorHandler extends AbstractDynamicThreadPoolMonitor {
private final static String METRIC_NAME_PREFIX = "dynamic.thread-pool"; private final static String METRIC_NAME_PREFIX = "dynamic.thread-pool";
@ -44,10 +43,6 @@ public class MicrometerMonitorHandler extends AbstractDynamicThreadPoolMonitor {
private final Map<String, ThreadPoolRunStateInfo> RUN_STATE_CACHE = new ConcurrentHashMap<>(); private final Map<String, ThreadPoolRunStateInfo> RUN_STATE_CACHE = new ConcurrentHashMap<>();
public MicrometerMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
super(threadPoolRunStateHandler);
}
@Override @Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
ThreadPoolRunStateInfo stateInfo = RUN_STATE_CACHE.get(poolRunStateInfo.getTpId()); ThreadPoolRunStateInfo stateInfo = RUN_STATE_CACHE.get(poolRunStateInfo.getTpId());

@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.micrometer;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.monitor.base.AbstractWebThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.Tag;
import org.springframework.core.env.Environment;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Web thread-pool micrometer monitor handler.
*/
public class WebThreadPoolMicrometerMonitorHandler extends AbstractWebThreadPoolMonitor {
private final static String METRIC_NAME_PREFIX = "web.thread-pool";
private final static String APPLICATION_NAME_TAG = "application.name";
private final Map<String, ThreadPoolRunStateInfo> RUN_STATE_CACHE = new ConcurrentHashMap<>();
@Override
protected void execute(ThreadPoolRunStateInfo webThreadPoolRunStateInfo) {
Environment environment = ApplicationContextHolder.getInstance().getEnvironment();
String applicationName = environment.getProperty("spring.application.name", "application");
ThreadPoolRunStateInfo stateInfo = RUN_STATE_CACHE.get(applicationName);
if (stateInfo == null) {
RUN_STATE_CACHE.put(applicationName, webThreadPoolRunStateInfo);
} else {
BeanUtil.convert(webThreadPoolRunStateInfo, stateInfo);
}
Iterable<Tag> tags = CollectionUtil.newArrayList(Tag.of(APPLICATION_NAME_TAG, applicationName));
Metrics.gauge(metricName("current.load"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getSimpleCurrentLoad);
Metrics.gauge(metricName("peak.load"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getSimplePeakLoad);
Metrics.gauge(metricName("core.size"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getCoreSize);
Metrics.gauge(metricName("maximum.size"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getMaximumSize);
Metrics.gauge(metricName("current.size"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getPoolSize);
Metrics.gauge(metricName("largest.size"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getLargestPoolSize);
Metrics.gauge(metricName("active.size"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getActiveSize);
Metrics.gauge(metricName("queue.size"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getQueueSize);
Metrics.gauge(metricName("queue.capacity"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getQueueCapacity);
Metrics.gauge(metricName("queue.remaining.capacity"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getQueueRemainingCapacity);
Metrics.gauge(metricName("completed.task.count"), tags, webThreadPoolRunStateInfo, ThreadPoolRunStateInfo::getCompletedTaskCount);
}
private String metricName(String name) {
return String.join(".", METRIC_NAME_PREFIX, name);
}
@Override
public String getType() {
return MonitorTypeEnum.MICROMETER.name().toLowerCase();
}
}

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>cn.hippo4j</groupId> <groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-all</artifactId> <artifactId>hippo4j-server</artifactId>
<version>${revision}</version> <version>${revision}</version>
</parent> </parent>
<artifactId>hippo4j-auth</artifactId> <artifactId>hippo4j-auth</artifactId>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save