Implement real-time parameter modification of the Spring bean thread pool instance. (#1295)

* Add common dependencies and realize basic functions.

* Update example config properties
pull/1298/head
yanrongzhen 1 year ago committed by GitHub
parent 5a124e85a9
commit 908671e887
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -41,7 +41,6 @@
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${bytebuddy.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

@ -17,6 +17,7 @@
package cn.hippo4j.agent.plugin.spring.boot.v1.define;
import cn.hippo4j.agent.core.plugin.WitnessMethod;
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import cn.hippo4j.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
@ -24,6 +25,9 @@ import cn.hippo4j.agent.core.plugin.match.ClassMatch;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import java.util.Collections;
import java.util.List;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static cn.hippo4j.agent.core.plugin.match.NameMatch.byName;
@ -86,4 +90,10 @@ public class EventPublishingRunListenerInstrumentation extends ClassInstanceMeth
}
};
}
@Override
protected List<WitnessMethod> witnessMethods() {
return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener",
named("finished")));
}
}

@ -50,7 +50,7 @@ public class EventPublishingFinishedInterceptor implements InstanceMethodsAround
ConfigurableApplicationContext context = (ConfigurableApplicationContext) allArguments[0];
if (context.getParent() != null) {
// After the child container is started, the thread pool registration will be carried out
SpringThreadPoolRegisterSupport.registerThreadPoolInstances();
SpringThreadPoolRegisterSupport.registerThreadPoolInstances(context);
return ret;
}
SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());

@ -17,6 +17,7 @@
package cn.hippo4j.agent.plugin.spring.boot.v2.define;
import cn.hippo4j.agent.core.plugin.WitnessMethod;
import cn.hippo4j.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import cn.hippo4j.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import cn.hippo4j.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
@ -24,6 +25,9 @@ import cn.hippo4j.agent.core.plugin.match.ClassMatch;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import java.util.Collections;
import java.util.List;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static cn.hippo4j.agent.core.plugin.match.NameMatch.byName;
@ -86,4 +90,10 @@ public class EventPublishingRunListenerInstrumentation extends ClassInstanceMeth
}
};
}
@Override
protected List<WitnessMethod> witnessMethods() {
return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener",
named("started")));
}
}

@ -47,7 +47,7 @@ public class EventPublishingStartedInterceptor implements InstanceMethodsAroundI
ConfigurableApplicationContext context = (ConfigurableApplicationContext) allArguments[0];
if (context.getParent() != null) {
// After the child container is started, the thread pool registration will be carried out
SpringThreadPoolRegisterSupport.registerThreadPoolInstances();
SpringThreadPoolRegisterSupport.registerThreadPoolInstances(context);
return ret;
}
SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());

@ -49,10 +49,10 @@ public class SpringBootConfig {
@SpringBootConfigNode(root = SpringBootConfig.class)
public static class Apollo {
public static final List<String> NAMESPACE = Arrays.asList("application");
public static List<String> NAMESPACE = Arrays.asList("application");
}
public static final String CONFIG_FILE_TYPE = null;
public static String CONFIG_FILE_TYPE;
}
}
}

@ -24,13 +24,18 @@ import cn.hippo4j.common.constant.Constants;
import cn.hippo4j.common.executor.support.BlockingQueueTypeEnum;
import cn.hippo4j.common.executor.support.RejectedPolicyTypeEnum;
import cn.hippo4j.common.toolkit.BooleanUtil;
import cn.hippo4j.core.executor.DynamicThreadPool;
import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
import cn.hippo4j.core.executor.support.adpter.DynamicThreadPoolAdapterChoose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@ -41,7 +46,7 @@ public class SpringThreadPoolRegisterSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringThreadPoolRegisterSupport.class);
public static void registerThreadPoolInstances() {
public static void registerThreadPoolInstances(ApplicationContext context) {
Map<ThreadPoolExecutor, Class<?>> earlyConstructMap = AgentThreadPoolInstanceRegistry.getInstance().earlyConstructMap;
for (Map.Entry<ThreadPoolExecutor, Class<?>> entry : earlyConstructMap.entrySet()) {
ThreadPoolExecutor enhancedInstance = entry.getKey();
@ -60,10 +65,30 @@ public class SpringThreadPoolRegisterSupport {
}
}
}
Map<String, Executor> beansWithAnnotation = context.getBeansOfType(Executor.class);
for (Map.Entry<String, Executor> entry : beansWithAnnotation.entrySet()) {
String beanName = entry.getKey();
Executor bean = entry.getValue();
ThreadPoolExecutor executor = null;
if (DynamicThreadPoolAdapterChoose.match(bean)) {
executor = DynamicThreadPoolAdapterChoose.unwrap(bean);
} else {
executor = (ThreadPoolExecutor) bean;
}
if (executor == null) {
LOGGER.warn("[Hippo4j-Agent] Thread pool is null, ignore bean registration. beanName={}, beanClass={}", beanName, bean.getClass().getName());
} else {
register(beanName, executor);
}
}
LOGGER.info("[Hippo4j-Agent] Registered thread pool instances successfully.");
}
public static void register(String threadPoolId, ThreadPoolExecutor executor) {
if (executor == null) {
return;
}
// build parameter properties.
Properties properties = new Properties();
properties.put(ThreadPoolPropertyKey.THREAD_POOL_ID, threadPoolId);

@ -69,6 +69,12 @@
<artifactId>hippo4j-agent-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-threadpool-common</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>

@ -0,0 +1,85 @@
# Copy the following to the apollo configuration file
spring.dynamic.thread-pool.web.core-pool-size=64
spring.dynamic.thread-pool.web.maximum-pool-size=128
spring.dynamic.thread-pool.web.keep-alive-time=1000
spring.dynamic.thread-pool.web.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=hippo4j
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 = cn.hippo4j.example.core.config.DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[0].thread-name-prefix = DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[0].core-pool-size = 2
spring.dynamic.thread-pool.executors[0].maximum-pool-size = 50
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 = hippo4j
spring.dynamic.thread-pool.executors[1].thread-pool-id = cn.hippo4j.example.core.config.DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[1].thread-name-prefix = DynamicThreadPoolConfig#FIELD2
spring.dynamic.thread-pool.executors[1].core-pool-size = 2
spring.dynamic.thread-pool.executors[1].maximum-pool-size = 50
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 = hippo4j
spring.dynamic.thread-pool.executors[2].thread-pool-id = messageConsumeTtlDynamicThreadPool
spring.dynamic.thread-pool.executors[2].thread-name-prefix = messageConsumeTtlDynamicThreadPool
spring.dynamic.thread-pool.executors[2].core-pool-size = 2
spring.dynamic.thread-pool.executors[2].maximum-pool-size = 50
spring.dynamic.thread-pool.executors[2].queue-capacity = 1024
spring.dynamic.thread-pool.executors[2].blocking-queue = ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[2].execute-time-out = 800
spring.dynamic.thread-pool.executors[2].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[2].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[2].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[2].alarm = true
spring.dynamic.thread-pool.executors[2].active-alarm = 80
spring.dynamic.thread-pool.executors[2].capacity-alarm = 80
spring.dynamic.thread-pool.executors[2].notify.interval = 8
spring.dynamic.thread-pool.executors[2].notify.receives = hippo4j
spring.dynamic.thread-pool.executors[3].thread-pool-id = messageProduceDynamicThreadPool
spring.dynamic.thread-pool.executors[3].thread-name-prefix = messageProduceDynamicThreadPool
spring.dynamic.thread-pool.executors[3].core-pool-size = 2
spring.dynamic.thread-pool.executors[3].maximum-pool-size = 50
spring.dynamic.thread-pool.executors[3].queue-capacity = 1024
spring.dynamic.thread-pool.executors[3].blocking-queue = ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[3].execute-time-out = 800
spring.dynamic.thread-pool.executors[3].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[3].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[3].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[3].alarm = true
spring.dynamic.thread-pool.executors[3].active-alarm = 80
spring.dynamic.thread-pool.executors[3].capacity-alarm = 80
spring.dynamic.thread-pool.executors[3].notify.interval = 8
spring.dynamic.thread-pool.executors[3].notify.receives = hippo4j

@ -0,0 +1,85 @@
# Copy the following to the apollo configuration file
spring.dynamic.thread-pool.web.core-pool-size=64
spring.dynamic.thread-pool.web.maximum-pool-size=128
spring.dynamic.thread-pool.web.keep-alive-time=1000
spring.dynamic.thread-pool.web.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=hippo4j
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 = cn.hippo4j.example.core.config.DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[0].thread-name-prefix = DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[0].core-pool-size = 2
spring.dynamic.thread-pool.executors[0].maximum-pool-size = 50
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 = hippo4j
spring.dynamic.thread-pool.executors[1].thread-pool-id = cn.hippo4j.example.core.config.DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[1].thread-name-prefix = DynamicThreadPoolConfig#FIELD2
spring.dynamic.thread-pool.executors[1].core-pool-size = 2
spring.dynamic.thread-pool.executors[1].maximum-pool-size = 50
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 = hippo4j
spring.dynamic.thread-pool.executors[2].thread-pool-id = messageConsumeTtlDynamicThreadPool
spring.dynamic.thread-pool.executors[2].thread-name-prefix = messageConsumeTtlDynamicThreadPool
spring.dynamic.thread-pool.executors[2].core-pool-size = 2
spring.dynamic.thread-pool.executors[2].maximum-pool-size = 50
spring.dynamic.thread-pool.executors[2].queue-capacity = 1024
spring.dynamic.thread-pool.executors[2].blocking-queue = ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[2].execute-time-out = 800
spring.dynamic.thread-pool.executors[2].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[2].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[2].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[2].alarm = true
spring.dynamic.thread-pool.executors[2].active-alarm = 80
spring.dynamic.thread-pool.executors[2].capacity-alarm = 80
spring.dynamic.thread-pool.executors[2].notify.interval = 8
spring.dynamic.thread-pool.executors[2].notify.receives = hippo4j
spring.dynamic.thread-pool.executors[3].thread-pool-id = messageProduceDynamicThreadPool
spring.dynamic.thread-pool.executors[3].thread-name-prefix = messageProduceDynamicThreadPool
spring.dynamic.thread-pool.executors[3].core-pool-size = 2
spring.dynamic.thread-pool.executors[3].maximum-pool-size = 50
spring.dynamic.thread-pool.executors[3].queue-capacity = 1024
spring.dynamic.thread-pool.executors[3].blocking-queue = ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[3].execute-time-out = 800
spring.dynamic.thread-pool.executors[3].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[3].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[3].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[3].alarm = true
spring.dynamic.thread-pool.executors[3].active-alarm = 80
spring.dynamic.thread-pool.executors[3].capacity-alarm = 80
spring.dynamic.thread-pool.executors[3].notify.interval = 8
spring.dynamic.thread-pool.executors[3].notify.receives = hippo4j

@ -48,22 +48,4 @@ 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
# For hippo4j-agent mode (Optional)
spring.dynamic.thread-pool.executors[2].thread-pool-id = cn.hippo4j.example.core.config.DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[2].thread-name-prefix = DynamicThreadPoolConfig#FIELD1
spring.dynamic.thread-pool.executors[2].core-pool-size = 2
spring.dynamic.thread-pool.executors[2].maximum-pool-size = 52
spring.dynamic.thread-pool.executors[2].queue-capacity = 1024
spring.dynamic.thread-pool.executors[2].blocking-queue = ResizableCapacityLinkedBlockingQueue
spring.dynamic.thread-pool.executors[2].execute-time-out = 800
spring.dynamic.thread-pool.executors[2].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[2].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[2].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[2].alarm = true
spring.dynamic.thread-pool.executors[2].active-alarm = 80
spring.dynamic.thread-pool.executors[2].capacity-alarm = 80
spring.dynamic.thread-pool.executors[2].notify.interval = 8
spring.dynamic.thread-pool.executors[2].notify.receives = nobodyiam
spring.dynamic.thread-pool.executors[1].notify.receives=chen.ma
Loading…
Cancel
Save