optimize plugin

This commit is contained in:
yanhom 2023-06-30 12:49:05 +08:00
parent a1ed6cd8ea
commit 69b2cc9707
26 changed files with 1277 additions and 1364 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ target/
!**/src/main/**/target/
!**/src/test/**/target/
.flattened-pom.xml
polaris/
### STS ###
.apt_generated

View File

@ -25,7 +25,19 @@ package org.dromara.dynamictp.common.ex;
**/
public class DtpException extends RuntimeException {
public DtpException() {
super();
}
public DtpException(String message) {
super(message);
}
public DtpException(String message, Throwable cause) {
super(message, cause);
}
public DtpException(Throwable cause) {
super(cause);
}
}

View File

@ -23,13 +23,34 @@ package org.dromara.dynamictp.core.plugin;
*/
public interface DtpInterceptor {
/**
* Intercept method.
*
* @param invocation invocation
* @return result
* @throws Throwable Throwable
*/
Object intercept(DtpInvocation invocation) throws Throwable;
/**
* Enhance object.
*
* @param target target object
* @return enhanced object
*/
default Object plugin(Object target) {
return DtpExtensionProxyFactory.enhance(target, this);
return DtpInterceptorProxyFactory.enhance(target, this);
}
/**
* Enhance object.
*
* @param target target object
* @param argumentTypes argument types
* @param arguments arguments
* @return enhanced object
*/
default Object plugin(Object target, Class<?>[] argumentTypes, Object[] arguments) {
return DtpExtensionProxyFactory.wrap(target, argumentTypes, arguments, this);
return DtpInterceptorProxyFactory.enhance(target, argumentTypes, arguments, this);
}
}

View File

@ -26,11 +26,10 @@ import java.util.Map;
import java.util.Set;
/**
* Proxy packaging class
* @author windsearcher.lq
* @since 1.1.4
*/
public class DtpExtensionProxy implements MethodInterceptor {
public class DtpInterceptorProxy implements MethodInterceptor {
private final Object target;
@ -38,7 +37,7 @@ public class DtpExtensionProxy implements MethodInterceptor {
private final Map<Class<?>, Set<Method>> signatureMap;
public DtpExtensionProxy(Object target, DtpInterceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
public DtpInterceptorProxy(Object target, DtpInterceptor interceptor, Map<Class<?>, Set<Method>> signatureMap) {
this.target = target;
this.interceptor = interceptor;
this.signatureMap = signatureMap;

View File

@ -17,29 +17,23 @@
package org.dromara.dynamictp.core.plugin;
import com.google.common.collect.Maps;
import net.sf.cglib.proxy.Enhancer;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* @author windsearcher.lq
* @since 1.1.4
*/
public class DtpExtensionProxyFactory {
public class DtpInterceptorProxyFactory {
public static Object enhance(Object target, DtpInterceptor interceptor) {
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
if (!signatureMap.containsKey(target.getClass())) {
return target;
}
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new DtpExtensionProxy(target, interceptor, signatureMap));
return enhancer.create();
return enhance(target, null, null, interceptor);
}
public static Object enhance(Object target, Class<?>[] argumentTypes, Object[] arguments, DtpInterceptor interceptor) {
@ -49,29 +43,28 @@ public class DtpExtensionProxyFactory {
}
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new DtpExtensionProxy(target, interceptor, signatureMap));
enhancer.setCallback(new DtpInterceptorProxy(target, interceptor, signatureMap));
if (Objects.isNull(argumentTypes) || Objects.isNull(arguments)) {
return enhancer.create();
}
return enhancer.create(argumentTypes, arguments);
}
private static Map<Class<?>, Set<Method>> getSignatureMap(DtpInterceptor interceptor) {
DtpExtensionPoint interceptsAnnotation = interceptor.getClass().getAnnotation(DtpExtensionPoint.class);
if (interceptsAnnotation == null) {
throw new RuntimeException("No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
DtpIntercepts interceptsAnno = interceptor.getClass().getAnnotation(DtpIntercepts.class);
if (interceptsAnno == null) {
throw new PluginException("No @DtpIntercepts annotation was found in interceptor " + interceptor.getClass().getName());
}
DtpSignature[] signatures = interceptsAnnotation.value();
if (signatures == null) {
throw new RuntimeException("@Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
}
Map<Class<?>, Set<Method>> signatureMap = new HashMap<>();
DtpSignature[] signatures = interceptsAnno.value();
Map<Class<?>, Set<Method>> signatureMap = Maps.newHashMap();
for (DtpSignature signature : signatures) {
Set<Method> methods = signatureMap.computeIfAbsent(signature.clazz(), k -> new HashSet<>());
try {
Method method = signature.clazz().getMethod(signature.method(), signature.args());
methods.add(method);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Could not find method on " + signature.clazz() + " named " + signature.method() + ". Cause: " + e, e);
throw new PluginException("Could not find method on " + signature.clazz() + " named " + signature.method() + ". Cause: " + e, e);
}
}
return signatureMap;

View File

@ -25,7 +25,7 @@ import java.util.List;
import java.util.ServiceLoader;
/**
* ExtensionRegistry related
* DtpInterceptorRegistry related
*
* @author windsearcher.lq
* @since 1.1.4
@ -34,35 +34,35 @@ import java.util.ServiceLoader;
public class DtpInterceptorRegistry {
/**
* Maintain all automatically registered and manually registered EXTENSIONS
* Maintain all automatically registered and manually registered INTERCEPTORS
*/
private static final List<DtpInterceptor> EXTENSIONS = new ArrayList<>();
private static final List<DtpInterceptor> INTERCEPTORS = new ArrayList<>();
static {
ServiceLoader<DtpInterceptor> loader = ServiceLoader.load(DtpInterceptor.class);
for (DtpInterceptor extension : loader) {
EXTENSIONS.add(extension);
for (DtpInterceptor interceptor : loader) {
INTERCEPTORS.add(interceptor);
}
}
public static void register(DtpInterceptor dtpInterceptor) {
log.info("DynamicTp register dtpExtension: {}", dtpInterceptor);
EXTENSIONS.add(dtpInterceptor);
log.info("DynamicTp register DtpInterceptor: {}", dtpInterceptor);
INTERCEPTORS.add(dtpInterceptor);
}
public static List<DtpInterceptor> getExtensions() {
return Collections.unmodifiableList(EXTENSIONS);
public static List<DtpInterceptor> getInterceptors() {
return Collections.unmodifiableList(INTERCEPTORS);
}
public static Object pluginAll(Object target) {
for (DtpInterceptor dtpInterceptor : EXTENSIONS) {
for (DtpInterceptor dtpInterceptor : INTERCEPTORS) {
target = dtpInterceptor.plugin(target);
}
return target;
}
public static Object pluginAll(Object target, Class<?>[] argumentTypes, Object[] arguments) {
for (DtpInterceptor dtpInterceptor : EXTENSIONS) {
for (DtpInterceptor dtpInterceptor : INTERCEPTORS) {
target = dtpInterceptor.plugin(target, argumentTypes, arguments);
}
return target;

View File

@ -28,7 +28,7 @@ import java.lang.annotation.Target;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DtpExtensionPoint {
public @interface DtpIntercepts {
DtpSignature[] value();

View File

@ -18,16 +18,31 @@
package org.dromara.dynamictp.core.plugin;
/**
* 签名用于指定具体需要拦截的类和对应的方法
* The annotation that indicate the method signature.
*
* @author windsearcher.lq
* @since 1.1.4
*/
public @interface DtpSignature {
/**
* Target class type.
*
* @return class type
*/
Class<?> clazz();
/**
* Method name.
*
* @return method name
*/
String method();
/**
* Method argument types.
*
* @return method argument types
*/
Class<?>[] args();
}

View File

@ -15,17 +15,31 @@
* limitations under the License.
*/
package org.dromara.dynamictp.example;
package org.dromara.dynamictp.core.plugin;
import org.dromara.dynamictp.core.spring.EnableDynamicTp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.dromara.dynamictp.common.ex.DtpException;
@EnableDynamicTp
@SpringBootApplication
public class ExtensionExampleApplication {
/**
* PluginException related
*
* @author yanhom
* @since 1.0.0
**/
public class PluginException extends DtpException {
public static void main(String[] args) {
SpringApplication.run(ExtensionExampleApplication.class, args);
public PluginException() {
super();
}
public PluginException(String message) {
super(message);
}
public PluginException(String message, Throwable cause) {
super(message, cause);
}
public PluginException(Throwable cause) {
super(cause);
}
}

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.dromara.dynamictp</groupId>
<artifactId>dynamic-tp-example</artifactId>
<version>1.1.3</version>
</parent>
<artifactId>dynamic-tp-example-extension</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!--自行管理jar,不使用父工程依赖,解决依赖版本问题-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.12.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.7</version>
</dependency>
<dependency>
<groupId>org.dromara.dynamictp</groupId>
<artifactId>dynamic-tp-spring-boot-starter-nacos</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.dromara.dynamictp</groupId>
<artifactId>dynamic-tp-spring-boot-starter-adapter-webserver</artifactId>
<version>${revision}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.dromara.dynamictp</groupId>-->
<!-- <artifactId>dynamic-tp-spring-boot-starter-extension-limiter-redis</artifactId>-->
<!-- <version>${revision}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,93 +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 org.dromara.dynamictp.example.config;
import org.dromara.dynamictp.core.support.DynamicTp;
import org.dromara.dynamictp.core.support.ThreadPoolBuilder;
import org.dromara.dynamictp.core.support.ThreadPoolCreator;
import org.dromara.dynamictp.core.thread.DtpExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static org.dromara.dynamictp.common.em.QueueTypeEnum.SYNCHRONOUS_QUEUE;
@Configuration
public class ThreadPoolConfiguration {
/**
* 通过{@link DynamicTp} 注解定义普通juc线程池会享受到该框架监控功能注解名称优先级高于方法名
*
* @return 线程池实例
*/
@DynamicTp("commonExecutor")
@Bean
public ThreadPoolExecutor commonExecutor() {
return (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
}
/**
* 通过{@link ThreadPoolCreator} 快速创建一些简单配置的动态线程池
* tips: 建议直接在配置中心配置就行不用@Bean声明
*
* @return 线程池实例
*/
@Bean
public DtpExecutor dtpExecutor1() {
return ThreadPoolCreator.createDynamicFast("dtpExecutor1");
}
/**
* 通过{@link ThreadPoolBuilder} 设置详细参数创建动态线程池推荐方式
* ioIntensive参考tomcat线程池设计实现了处理io密集型任务的线程池具体参数可以看代码注释
*
* tips: 建议直接在配置中心配置就行不用@Bean声明
* @return 线程池实例
*/
@Bean
public DtpExecutor ioIntensiveExecutor() {
return ThreadPoolBuilder.newBuilder()
.threadPoolName("ioIntensiveExecutor")
.corePoolSize(20)
.maximumPoolSize(50)
.queueCapacity(2048)
.ioIntensive(true)
.buildDynamic();
}
/**
* tips: 建议直接在配置中心配置就行不用@Bean声明
* @return 线程池实例
*/
@Bean
public ThreadPoolExecutor dtpExecutor2() {
return ThreadPoolBuilder.newBuilder()
.threadPoolName("dtpExecutor2")
.corePoolSize(10)
.maximumPoolSize(15)
.keepAliveTime(15000)
.timeUnit(TimeUnit.MILLISECONDS)
.workQueue(SYNCHRONOUS_QUEUE.getName(), null, false, null)
.waitForTasksToCompleteOnShutdown(true)
.awaitTerminationSeconds(5)
.buildDynamic();
}
}

View File

@ -1,73 +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 org.dromara.dynamictp.example.controller;
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.DtpRegistry;
import org.dromara.dynamictp.core.support.task.runnable.NamedRunnable;
import org.dromara.dynamictp.core.thread.DtpExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@RestController
@SuppressWarnings("all")
public class TestController {
@Resource
private ThreadPoolExecutor dtpExecutor1;
@GetMapping("/dtp-nacos-example/test")
public String test() throws InterruptedException {
task();
return "success";
}
public void task() throws InterruptedException {
DtpExecutor dtpExecutor2 = (DtpExecutor) DtpRegistry.getExecutor("dtpExecutor2");
Executor dtpExecutor12 = DtpRegistry.getExecutor("dtpExecutor12");
dtpExecutor2.getThreadPoolAliasName();
for (int i = 0; i < 2; i++) {
Thread.sleep(100);
// dtpExecutor1.execute(() -> {
// log.info("i am dynamic-tp-test-1 task");
// });
dtpExecutor2.execute(NamedRunnable.of(() -> {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
log.info("i am dynamic-tp-test-2 task");
}, "task-" + i));
dtpExecutor12.execute(NamedRunnable.of(() -> {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
log.info("i am dynamic-tp-test-12 task");
}, "task-" + i));
}
}
}

View File

@ -1,42 +0,0 @@
server:
port: 8888
servlet:
context-path: "/dynamic-tp"
# 开启 SpringBoot Actuator Endpoint 暴露出DynamicTp指标接口
# 开启 prometheus 指标采集端点
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: '*' # 测试使用,线上不要用*,按需开启
spring:
application:
name: dynamic-tp-nacos-demo
profiles:
active: dev
dynamic:
tp:
extensions:
- extensionPath: org.dromara.dynamictp.example.extensiontest.TestExtension
nacos:
config:
server-addr: 127.0.0.1:8848
type: yaml
data-ids: dynamic-tp-nacos-demo-dev.yml,dynamic-tp-nacos-demo-dtp-dev.yml # 线程池配置文件必须要在此处配置
auto-refresh: true
group: DEFAULT_GROUP
bootstrap:
enable: true
log-enable: true
logging:
level:
#root: DEBUG
com.alibaba.nacos.client.config.impl: DEBUG

View File

@ -1,88 +0,0 @@
# 动态线程池配置文件,建议单独开一个文件放到配置中心,字段详解看readme介绍
spring:
dynamic:
tp:
enabled: true
enabledBanner: true # 是否开启banner打印,默认true
enabledCollect: true # 是否开启监控指标采集,默认false
collectorTypes: micrometer,logging,endpoint # 监控数据采集器类型(logging | micrometer | internal_logging),默认micrometer
logPath: D:\\logs # 监控日志数据路径,默认 ${user.home}/logs
monitorInterval: 5 # 监控时间间隔(报警判断、指标采集),默认5s
nacos: # nacos配置,不配置有默认值(规则name-dev.yml这样),cloud应用不需要配置
dataId: dynamic-tp-nacos-demo-dtp-dev.yml
group: DEFAULT_GROUP
configType: yml # 配置文件类型
platforms: # 通知报警平台配置
- platform: wechat
urlKey: 3a7500-1287-4bd-a798-c5c3d8b69c # 替换
receivers: test1,test2 # 接受人企微名称
- platform: ding
urlKey: f80dad441fcd655438f4a08dcd6a # 替换
secret: SECb5441fa6f375d5b9d21 # 替换,非sign模式可以没有此值
receivers: 15810119805 # 钉钉账号手机号
- platform: lark
urlKey: 0d944ae7-b24a-40 # 替换
receivers: test1,test2 # 接受人飞书名称/openid
tomcatTp: # tomcat web server线程池配置
corePoolSize: 100
maximumPoolSize: 400
keepAliveTime: 60
jettyTp: # jetty web server线程池配置
corePoolSize: 100
maximumPoolSize: 400
undertowTp: # undertow web server线程池配置
corePoolSize: 100
maximumPoolSize: 400
keepAliveTime: 60
hystrixTp: # hystrix 线程池配置
- threadPoolName: hystrix1
corePoolSize: 100
maximumPoolSize: 400
keepAliveTime: 60
dubboTp: # dubbo 线程池配置
- threadPoolName: dubboTp#20880
corePoolSize: 100
maximumPoolSize: 400
keepAliveTime: 60
rocketMqTp: # rocketmq 线程池配置
- threadPoolName: group1#topic1
corePoolSize: 200
maximumPoolSize: 400
keepAliveTime: 60
executors: # 动态线程池配置,都有默认值,采用默认值的可以不配置该项,减少配置量
- threadPoolName: dtpExecutor1
executorType: common # 线程池类型common、eager:适用于io密集型
corePoolSize: 6
maximumPoolSize: 8
queueCapacity: 200
queueType: VariableLinkedBlockingQueue # 任务队列,查看源码QueueTypeEnum枚举类
rejectedHandlerType: CallerRunsPolicy # 拒绝策略,查看RejectedTypeEnum枚举类
keepAliveTime: 50
allowCoreThreadTimeOut: false # 是否允许核心线程池超时
threadNamePrefix: test # 线程名前缀
waitForTasksToCompleteOnShutdown: false # 参考spring线程池设计,优雅关闭线程池
awaitTerminationSeconds: 5 # 单位(s)
preStartAllCoreThreads: false # 是否预热所有核心线程,默认false
runTimeout: 200 # 任务执行超时阈值,目前只做告警用,单位(ms)
queueTimeout: 100 # 任务在队列等待超时阈值,目前只做告警用,单位(ms)
taskWrapperNames: ["ttl"] # 任务包装器名称,集成TaskWrapper接口
notifyItems: # 报警项,不配置自动会按默认值配置(变更通知、容量报警、活性报警、拒绝报警、任务超时报警)
- type: capacity # 报警项类型,查看源码 NotifyTypeEnum枚举类
enabled: true
threshold: 80 # 报警阈值
platforms: [ding,wechat] # 可选配置,不配置默认拿上层platforms配置的所以平台
interval: 120 # 报警间隔(单位:s)
- type: change
enabled: true
- type: liveness
enabled: true
threshold: 80
- type: reject
enabled: true
threshold: 1
- type: run_timeout
enabled: true
threshold: 1
- type: queue_timeout
enabled: true
threshold: 1

View File

@ -1,875 +0,0 @@
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 6,
"iteration": 1650595506578,
"links": [],
"panels": [
{
"datasource": null,
"description": "当前线程数",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "hue",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineStyle": {
"fill": "solid"
},
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 12,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_current_size{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}",
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "A"
}
],
"title": "当前线程数",
"transparent": true,
"type": "timeseries"
},
{
"datasource": null,
"description": "活跃线程数",
"fieldConfig": {
"defaults": {
"color": {
"mode": "continuous-GrYlRd"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 8,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_active_count{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}",
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "A"
}
],
"title": "活跃线程数",
"type": "timeseries"
},
{
"datasource": null,
"description": "任务队列大小",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 8
},
"id": 6,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_queue_size{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}\n",
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "A"
}
],
"title": "任务队列大小",
"type": "timeseries"
},
{
"datasource": null,
"description": "任务队列剩余大小",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "smooth",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": true,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "orange",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"id": 2,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"pluginVersion": "8.3.3",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_queue_remaining_capacity{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}",
"hide": false,
"interval": "",
"intervalFactor": 1,
"legendFormat": "{{thread_pool_name}}",
"refId": "B"
}
],
"title": "任务队列剩余大小",
"type": "timeseries"
},
{
"datasource": null,
"description": "完成任务数",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 16
},
"id": 10,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_completed_task_count{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}",
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "A"
}
],
"title": "完成任务数",
"type": "timeseries"
},
{
"datasource": null,
"description": "拒绝任务数",
"fieldConfig": {
"defaults": {
"color": {
"mode": "continuous-reds"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": true,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 16
},
"id": 4,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"pluginVersion": "8.3.3",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_reject_count{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}\n",
"format": "time_series",
"hide": false,
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "B"
}
],
"title": "拒绝任务数",
"type": "timeseries"
},
{
"datasource": null,
"description": "执行超时任务数",
"fieldConfig": {
"defaults": {
"color": {
"mode": "continuous-reds"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 24
},
"id": 14,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_run_timeout_count{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}",
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "A"
}
],
"title": "执行超时任务数",
"type": "timeseries"
},
{
"datasource": null,
"description": "队列等待超时任务数",
"fieldConfig": {
"defaults": {
"color": {
"mode": "continuous-reds"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 5,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 7,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 24
},
"id": 16,
"links": [
{
"title": "https://github.com/lyh200/dynamic-tp",
"url": "https://github.com/lyh200/dynamic-tp"
}
],
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "WcpShMYnk"
},
"exemplar": true,
"expr": "thread_pool_queue_timeout_count{app_name=\"$application\", instance=\"$instance\", thread_pool_name=\"$threadpool\"}",
"interval": "",
"legendFormat": "{{thread_pool_name}}",
"refId": "A"
}
],
"title": "队列等待超时任务数",
"type": "timeseries"
}
],
"refresh": "5s",
"schemaVersion": 30,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"allValue": null,
"current": {
"selected": false,
"text": "dynamic-tp-nacos-cloud-demo",
"value": "dynamic-tp-nacos-cloud-demo"
},
"datasource": null,
"definition": "label_values(app_name)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": "Application",
"multi": false,
"name": "application",
"options": [],
"query": {
"query": "label_values(app_name)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"allValue": null,
"current": {
"selected": true,
"text": "10.2.109.132:9100",
"value": "10.2.109.132:9100"
},
"datasource": null,
"definition": "label_values({app_name=\"$application\"}, instance)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": "Instance",
"multi": false,
"name": "instance",
"options": [],
"query": {
"query": "label_values({app_name=\"$application\"}, instance)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"allValue": null,
"current": {
"selected": true,
"text": "dtpExecutor2",
"value": "dtpExecutor2"
},
"datasource": null,
"definition": "label_values({app_name=\"$application\"}, thread_pool_name)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": "ThreadPoolName",
"multi": false,
"name": "threadpool",
"options": [],
"query": {
"query": "label_values({app_name=\"$application\"}, thread_pool_name)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
}
]
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "线程池监控(DynamicTp)",
"uid": "5wBx-ysnk",
"version": 7
}

View File

@ -41,11 +41,11 @@ public class ThreadPoolConfiguration {
*
* @return 线程池实例
*/
// @DynamicTp("commonExecutor")
// @Bean
// public ThreadPoolExecutor commonExecutor() {
// return (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
// }
@DynamicTp("commonExecutor")
@Bean
public ThreadPoolExecutor commonExecutor() {
return (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
}
/**
* 通过{@link ThreadPoolCreator} 快速创建一些简单配置的动态线程池
@ -65,32 +65,32 @@ public class ThreadPoolConfiguration {
* tips: 建议直接在配置中心配置就行不用@Bean声明
* @return 线程池实例
*/
// @Bean
// public DtpExecutor ioIntensiveExecutor() {
// return ThreadPoolBuilder.newBuilder()
// .threadPoolName("ioIntensiveExecutor")
// .corePoolSize(20)
// .maximumPoolSize(50)
// .queueCapacity(2048)
// .ioIntensive(true)
// .buildDynamic();
// }
@Bean
public DtpExecutor ioIntensiveExecutor() {
return ThreadPoolBuilder.newBuilder()
.threadPoolName("ioIntensiveExecutor")
.corePoolSize(20)
.maximumPoolSize(50)
.queueCapacity(2048)
.ioIntensive(true)
.buildDynamic();
}
/**
* tips: 建议直接在配置中心配置就行不用@Bean声明
* @return 线程池实例
*/
// @Bean
// public ThreadPoolExecutor dtpExecutor2() {
// return ThreadPoolBuilder.newBuilder()
// .threadPoolName("dtpExecutor2")
// .corePoolSize(10)
// .maximumPoolSize(15)
// .keepAliveTime(15000)
// .timeUnit(TimeUnit.MILLISECONDS)
// .workQueue(SYNCHRONOUS_QUEUE.getName(), null, false, null)
// .waitForTasksToCompleteOnShutdown(true)
// .awaitTerminationSeconds(5)
// .buildDynamic();
// }
@Bean
public ThreadPoolExecutor dtpExecutor2() {
return ThreadPoolBuilder.newBuilder()
.threadPoolName("dtpExecutor2")
.corePoolSize(10)
.maximumPoolSize(15)
.keepAliveTime(15000)
.timeUnit(TimeUnit.MILLISECONDS)
.workQueue(SYNCHRONOUS_QUEUE.getName(), null, false, null)
.waitForTasksToCompleteOnShutdown(true)
.awaitTerminationSeconds(5)
.buildDynamic();
}
}

View File

@ -18,10 +18,13 @@
package org.dromara.dynamictp.example.controller;
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.DtpRegistry;
import org.dromara.dynamictp.core.support.task.runnable.NamedRunnable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
@ -42,20 +45,20 @@ public class TestController {
}
public void task() throws InterruptedException {
// Executor dtpExecutor2 = DtpRegistry.getExecutor("dtpExecutor2");
// for (int i = 0; i < 100; i++) {
// Thread.sleep(100);
// dtpExecutor1.execute(() -> {
// log.info("i am dynamic-tp-test-1 task");
// });
// dtpExecutor2.execute(NamedRunnable.of(() -> {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// log.info("i am dynamic-tp-test-2 task");
// }, "task-" + i));
// }
Executor dtpExecutor2 = DtpRegistry.getExecutor("dtpExecutor2");
for (int i = 0; i < 100; i++) {
Thread.sleep(100);
dtpExecutor1.execute(() -> {
log.info("i am dynamic-tp-test-1 task");
});
dtpExecutor2.execute(NamedRunnable.of(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("i am dynamic-tp-test-2 task");
}, "task-" + i));
}
}
}

View File

@ -0,0 +1,50 @@
/*
* 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 org.dromara.dynamictp.example.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.plugin.DtpInterceptor;
import org.dromara.dynamictp.core.plugin.DtpIntercepts;
import org.dromara.dynamictp.core.plugin.DtpInvocation;
import org.dromara.dynamictp.core.plugin.DtpSignature;
import org.dromara.dynamictp.core.thread.DtpExecutor;
import org.dromara.dynamictp.core.thread.ScheduledDtpExecutor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author windsearcher.lq
*/
@DtpIntercepts({
@DtpSignature(clazz = DtpExecutor.class, method = "execute", args = {Runnable.class}),
@DtpSignature(clazz = ScheduledDtpExecutor.class, method = "execute", args = {Runnable.class})
})
@Slf4j
public class TestExecuteInterceptor implements DtpInterceptor {
@Override
public Object intercept(DtpInvocation invocation) throws InvocationTargetException, IllegalAccessException {
DtpExecutor dtpExecutor = (DtpExecutor) invocation.getTarget();
String method = invocation.getMethod().getName();
Object[] args = invocation.getArgs();
log.info("TestExecuteInterceptor: dtpExecutor: {}, method: {}, args: {}", dtpExecutor, method, args);
return invocation.proceed();
}
}

View File

@ -0,0 +1 @@
org.dromara.dynamictp.example.interceptor.TestExecuteInterceptor

View File

@ -15,43 +15,35 @@
* limitations under the License.
*/
package org.dromara.dynamictp.example.extensiontest;
package org.dromara.dynamictp.example.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.plugin.DtpInterceptor;
import org.dromara.dynamictp.core.plugin.DtpExtensionPoint;
import org.dromara.dynamictp.core.plugin.DtpIntercepts;
import org.dromara.dynamictp.core.plugin.DtpInvocation;
import org.dromara.dynamictp.core.plugin.DtpSignature;
import org.dromara.dynamictp.core.thread.DtpExecutor;
import org.dromara.dynamictp.core.thread.ScheduledDtpExecutor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.TimeUnit;
@DtpExtensionPoint({@DtpSignature(clazz = DtpExecutor.class, method = "execute", args = {Runnable.class}), @DtpSignature(clazz = ScheduledDtpExecutor.class, method = "execute", args = {Runnable.class})})
/**
* @author windsearcher.lq
*/
@DtpIntercepts({
@DtpSignature(clazz = DtpExecutor.class, method = "execute", args = {Runnable.class}),
@DtpSignature(clazz = ScheduledDtpExecutor.class, method = "execute", args = {Runnable.class})
})
@Slf4j
public class TestInterceptor implements DtpInterceptor {
public class TestExecuteInterceptor implements DtpInterceptor {
@Override
public Object intercept(DtpInvocation invocation) throws InvocationTargetException, IllegalAccessException {
System.out.println("--------------线程池开始执行任务-------------");
DtpExecutor dtpExecutor = (DtpExecutor) invocation.getTarget();
log.info("dtpExecutor name: {}, maximum size: {}, {}, {}, {}", dtpExecutor.getThreadPoolName(),
dtpExecutor.getMaximumPoolSize(), dtpExecutor.getThreadPoolName(), dtpExecutor.getQueueCapacity(),
dtpExecutor.getKeepAliveTime(TimeUnit.MILLISECONDS));
Object result = invocation.proceed();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("--------------线程池结束执行任务-------------");
return result;
String method = invocation.getMethod().getName();
Object[] args = invocation.getArgs();
log.info("TestExecuteInterceptor: dtpExecutor: {}, method: {}, args: {}", dtpExecutor, method, args);
return invocation.proceed();
}
}

View File

@ -0,0 +1 @@
org.dromara.dynamictp.example.interceptor.TestExecuteInterceptor

View File

@ -26,7 +26,6 @@
<module>example-adapter</module>
<module>example-polaris-cloud</module>
<module>example-huawei-cloud</module>
<module>example-extension</module>
</modules>
<build>

View File

1061
polaris/logs/polaris.log Normal file

File diff suppressed because it is too large Load Diff