diff --git a/agent/hippo4j-agent-bootstrap/pom.xml b/agent/hippo4j-agent-bootstrap/pom.xml index 8504850d9d..c356aab407 100644 --- a/agent/hippo4j-agent-bootstrap/pom.xml +++ b/agent/hippo4j-agent-bootstrap/pom.xml @@ -33,6 +33,7 @@ maven-shade-plugin + 3.4.1 package diff --git a/agent/hippo4j-agent-core/pom.xml b/agent/hippo4j-agent-core/pom.xml index ee49874b5d..b21dc0df25 100644 --- a/agent/hippo4j-agent-core/pom.xml +++ b/agent/hippo4j-agent-core/pom.xml @@ -29,6 +29,7 @@ org.slf4j ${shade.package}.${shade.org.slf4j.source} 1.18.0 + 2.3.1 @@ -78,15 +79,16 @@ hippo4j-threadpool-infra-common ${project.version} + - cn.hippo4j - hippo4j-threadpool-dynamic-mode-config - ${project.version} + javax.xml.bind + jaxb-api + ${jaxb.version} - cn.hippo4j - hippo4j-threadpool-kernel-monitor - ${project.version} + com.sun.xml.bind + jaxb-impl + ${jaxb.version} @@ -107,6 +109,7 @@ maven-shade-plugin + 3.4.1 package diff --git a/agent/hippo4j-agent-plugin/apollo-plugin/src/main/java/cn/hippo4j/agent/plugin/apollo/ApolloDynamicThreadPoolChangeHandler.java b/agent/hippo4j-agent-plugin/apollo-plugin/src/main/java/cn/hippo4j/agent/plugin/apollo/ApolloDynamicThreadPoolChangeHandler.java index d6e035ff50..77784263e6 100644 --- a/agent/hippo4j-agent-plugin/apollo-plugin/src/main/java/cn/hippo4j/agent/plugin/apollo/ApolloDynamicThreadPoolChangeHandler.java +++ b/agent/hippo4j-agent-plugin/apollo-plugin/src/main/java/cn/hippo4j/agent/plugin/apollo/ApolloDynamicThreadPoolChangeHandler.java @@ -29,7 +29,6 @@ import com.ctrip.framework.apollo.ConfigService; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; import com.ctrip.framework.apollo.model.ConfigChange; -import org.springframework.boot.context.properties.bind.Binder; import java.util.HashMap; import java.util.List; @@ -72,7 +71,7 @@ public void registerListener() { /** * Builds and binds the {@link BootstrapConfigProperties} from the given configuration map. *

- * This method uses Spring's {@link Binder} to bind the configuration values to an instance + * This method uses SpringPropertyBinder to bind the configuration values to an instance * of {@link BootstrapConfigProperties}, which can then be used to configure the thread pool * dynamically. * diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml b/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml index f048923f6d..986f041ebd 100644 --- a/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml +++ b/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml @@ -26,6 +26,11 @@ hippo4j-threadpool-dynamic-mode-config ${project.version} + + org.springframework + spring-context + provided + com.alibaba.nacos nacos-client diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/NacosDynamicThreadPoolChangeHandler.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/NacosDynamicThreadPoolChangeHandler.java index 8537f45c4e..691719ecff 100644 --- a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/NacosDynamicThreadPoolChangeHandler.java +++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/NacosDynamicThreadPoolChangeHandler.java @@ -32,7 +32,6 @@ import com.alibaba.nacos.api.PropertyKeyConst; import com.alibaba.nacos.api.config.ConfigService; import com.alibaba.nacos.api.config.listener.Listener; -import org.springframework.boot.context.properties.bind.Binder; import java.io.IOException; import java.util.HashMap; @@ -124,7 +123,7 @@ public Executor getExecutor() { /** * Builds and binds the {@link BootstrapConfigProperties} from the given configuration map. *

- * This method uses Spring's {@link Binder} to bind the configuration values to an instance + * This method uses SpringPropertyBinder to bind the configuration values to an instance * of {@link BootstrapConfigProperties}, which can then be used to configure the thread pool * dynamically. * diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosConfigConstructorInterceptor.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosConfigConstructorInterceptor.java index 9241710f21..e4379ce8ac 100644 --- a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosConfigConstructorInterceptor.java +++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosConfigConstructorInterceptor.java @@ -49,7 +49,7 @@ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws } // The Nacos plugin triggers before the Spring configuration plug-in. - // This means that when the Apollo plug-in executes, Spring's Environment is not yet ready, + // This means that when the Nacos plugin executes, Spring's Environment is not yet ready, // so the configuration cannot be read // After listening to the AGENT_SPRING_PROPERTIES_LOADER_COMPLETED event, register the listener for Nacos AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.AGENT_SPRING_PROPERTIES_LOADER_COMPLETED, new NacosConfigPropertiesLoaderCompletedListener()); diff --git a/agent/hippo4j-agent-plugin/pom.xml b/agent/hippo4j-agent-plugin/pom.xml index 0217b17b92..b2bae3f431 100644 --- a/agent/hippo4j-agent-plugin/pom.xml +++ b/agent/hippo4j-agent-plugin/pom.xml @@ -38,6 +38,12 @@ cn.hippo4j hippo4j-agent-core ${project.version} + + + org.springframework + spring-core + + provided diff --git a/agent/hippo4j-agent-plugin/spring-plugins/pom.xml b/agent/hippo4j-agent-plugin/spring-plugins/pom.xml index 42b725b5ec..f9ff2a2a19 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/pom.xml +++ b/agent/hippo4j-agent-plugin/spring-plugins/pom.xml @@ -15,6 +15,7 @@ spring-boot-1x-plugin spring-boot-2x-plugin + spring-boot-3x-plugin spring-plugin-common diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml index 1c0a7fc184..1a020f30f0 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/pom.xml @@ -13,7 +13,6 @@ 1.5.22.RELEASE - 1.9.1 diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/boot/SpringBootV1PluginBootService.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/boot/SpringBootV1PluginBootService.java new file mode 100644 index 0000000000..2ab4a1c3ad --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/boot/SpringBootV1PluginBootService.java @@ -0,0 +1,52 @@ +/* + * 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.agent.plugin.spring.boot.v1.boot; + +import cn.hippo4j.agent.core.boot.BootService; +import cn.hippo4j.agent.core.boot.DefaultImplementor; +import cn.hippo4j.common.logging.api.ILog; +import cn.hippo4j.common.logging.api.LogManager; + +/** + * SpringBoot v1 plugin boot service + */ +@DefaultImplementor +public class SpringBootV1PluginBootService implements BootService { + + private static final ILog LOGGER = LogManager.getLogger(SpringBootV1PluginBootService.class); + + @Override + public void prepare() throws Throwable { + + } + + @Override + public void boot() throws Throwable { + LOGGER.info("Loader SpringBootV1PluginBootService..."); + } + + @Override + public void onComplete() throws Throwable { + + } + + @Override + public void shutdown() throws Throwable { + + } +} diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/ApplicationContextInstrumentation.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/EventPublishingRunListenerInstrumentationV1.java similarity index 83% rename from agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/ApplicationContextInstrumentation.java rename to agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/EventPublishingRunListenerInstrumentationV1.java index 315f3a96b2..a87dd7326a 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/ApplicationContextInstrumentation.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/EventPublishingRunListenerInstrumentationV1.java @@ -32,13 +32,13 @@ import static net.bytebuddy.matcher.ElementMatchers.named; /** - * Application Context Refresh instrumentation + * SpringBoot v1 EventPublishingRunListener Finished instrumentation */ -public class ApplicationContextInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class EventPublishingRunListenerInstrumentationV1 extends ClassInstanceMethodsEnhancePluginDefine { - private static final String ENHANCE_CLASS = "org.springframework.context.support.AbstractApplicationContext"; + private static final String ENHANCE_CLASS = "org.springframework.boot.context.event.EventPublishingRunListener"; - private static final String APPLICATION_CONTEXT_REFRESH_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.boot.v1.interceptor.ApplicationContextInterceptor"; + private static final String EVENT_PUBLISHING_FINISHED_INTERCEPTOR_V1 = "cn.hippo4j.agent.plugin.spring.boot.v1.interceptor.EventPublishingRunListenerFinishedInterceptorV1"; @Override protected ClassMatch enhanceClass() { @@ -56,12 +56,12 @@ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { @Override public ElementMatcher getMethodsMatcher() { - return named("refresh"); + return named("finished"); } @Override public String getMethodsInterceptor() { - return APPLICATION_CONTEXT_REFRESH_INTERCEPTOR; + return EVENT_PUBLISHING_FINISHED_INTERCEPTOR_V1; } @Override diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/ApplicationContextInterceptor.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingRunListenerFinishedInterceptorV1.java similarity index 83% rename from agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/ApplicationContextInterceptor.java rename to agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingRunListenerFinishedInterceptorV1.java index b0b1666583..9d268d34ed 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/ApplicationContextInterceptor.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingRunListenerFinishedInterceptorV1.java @@ -33,9 +33,9 @@ import java.util.concurrent.atomic.AtomicBoolean; /** - * Application Context Refresh interceptor + * EventPublishingRunListener Finished interceptor */ -public class ApplicationContextInterceptor implements InstanceMethodsAroundInterceptor { +public class EventPublishingRunListenerFinishedInterceptorV1 implements InstanceMethodsAroundInterceptor { private static final AtomicBoolean isExecuted = new AtomicBoolean(false); @@ -46,10 +46,9 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - // Since the refresh() method is a method of the AbstractApplicationContext class, - // the AbstractApplicationContext itself is an implementation class of the ApplicationContext. - // Therefore, can treat the class instance itself as an ApplicationContext object. - ConfigurableApplicationContext context = (ConfigurableApplicationContext) objInst; + // Since the finished() method is a method of the EventPublishingRunListener class, + // the EventPublishingRunListener the first parameter is ConfigurableApplicationContext + ConfigurableApplicationContext context = (ConfigurableApplicationContext) allArguments[0]; if (context.getParent() != null) { // After the child container is started, the thread pool registration will be carried out // IDEA's runtime environment or debugging mechanisms make context refresh speeds different. @@ -70,8 +69,12 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA if (isExecuted.compareAndSet(false, true)) { ApplicationContextHolder contextHolder = new ApplicationContextHolder(); contextHolder.setApplicationContext(context); + // Load Spring Properties SpringPropertiesLoader.loadSpringProperties(context.getEnvironment()); - AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener()); + // register Dynamic ThreadPool Refresh Listener + if (AbstractSubjectCenter.get(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH) == null) { + AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener()); + } } return ret; } diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService new file mode 100644 index 0000000000..589da57589 --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService @@ -0,0 +1,17 @@ +# 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. + +cn.hippo4j.agent.plugin.spring.boot.v1.boot.SpringBootV1PluginBootService \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/hippo4j-plugin.def b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/hippo4j-plugin.def index 403de5ce12..eb4a03762c 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/hippo4j-plugin.def +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/hippo4j-plugin.def @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -spring-boot-1.x=cn.hippo4j.agent.plugin.spring.boot.v1.define.ApplicationContextInstrumentation +spring-boot-1.x=cn.hippo4j.agent.plugin.spring.boot.v1.define.EventPublishingRunListenerInstrumentationV1 diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/boot/SpringBootV2PluginBootService.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/boot/SpringBootV2PluginBootService.java index d4763704cd..8a97116b0e 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/boot/SpringBootV2PluginBootService.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/boot/SpringBootV2PluginBootService.java @@ -23,7 +23,7 @@ import cn.hippo4j.common.logging.api.LogManager; /** - * SpringBoot v1 plugin boot service + * SpringBoot v2 plugin boot service */ @DefaultImplementor public class SpringBootV2PluginBootService implements BootService { diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/define/EventPublishingRunListenerInstrumentation.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/define/EventPublishingRunListenerInstrumentationV2.java similarity index 74% rename from agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/define/EventPublishingRunListenerInstrumentation.java rename to agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/define/EventPublishingRunListenerInstrumentationV2.java index 34d36c390e..f305b2d2ac 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/define/EventPublishingRunListenerInstrumentation.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/define/EventPublishingRunListenerInstrumentationV2.java @@ -25,20 +25,21 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; -import java.util.Collections; +import java.util.Arrays; import java.util.List; import static net.bytebuddy.matcher.ElementMatchers.named; import static cn.hippo4j.agent.core.plugin.match.NameMatch.byName; +import static net.bytebuddy.matcher.ElementMatchers.not; /** - * Event publishing run listener instrumentation + * SpringBoot v2 Event publishing run listener instrumentation */ -public class EventPublishingRunListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class EventPublishingRunListenerInstrumentationV2 extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "org.springframework.boot.context.event.EventPublishingRunListener"; - private static final String EVENT_PUBLISHING_FINISHED_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.boot.v2.interceptor.EventPublishingStartedInterceptor"; + private static final String EVENT_PUBLISHING_STARTED_INTERCEPTOR_V2 = "cn.hippo4j.agent.plugin.spring.boot.v2.interceptor.EventPublishingStartedInterceptorV2"; private static final String EVENT_PUBLISHING_ENVIRONMENT_PREPARED_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.common.interceptor.EventPublishingRunListenerEnvironmentPreparedInterceptor"; @Override @@ -63,7 +64,7 @@ public ElementMatcher getMethodsMatcher() { @Override public String getMethodsInterceptor() { - return EVENT_PUBLISHING_FINISHED_INTERCEPTOR; + return EVENT_PUBLISHING_STARTED_INTERCEPTOR_V2; } @Override @@ -93,7 +94,17 @@ public boolean isOverrideArgs() { @Override protected List witnessMethods() { - return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", - named("started"))); + return Arrays.asList( + new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", named("started")), + new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", named("running")), + new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", not(named("ready"))) + // new WitnessMethod("org.springframework.boot.context.properties.ConstructorBinding", not(isAnnotatedWith(Deprecated.class))) + ); } + + @Override + protected String[] witnessClasses() { + return new String[]{"org.springframework.boot.context.properties.ConstructorBinding"}; + } + } diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/interceptor/EventPublishingStartedInterceptor.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/interceptor/EventPublishingStartedInterceptorV2.java similarity index 88% rename from agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/interceptor/EventPublishingStartedInterceptor.java rename to agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/interceptor/EventPublishingStartedInterceptorV2.java index 74faef32f1..cf8cab9deb 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/interceptor/EventPublishingStartedInterceptor.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v2/interceptor/EventPublishingStartedInterceptorV2.java @@ -35,11 +35,11 @@ /** * Event publishing started interceptor */ -public class EventPublishingStartedInterceptor implements InstanceMethodsAroundInterceptor { +public class EventPublishingStartedInterceptorV2 implements InstanceMethodsAroundInterceptor { private static final AtomicBoolean isExecuted = new AtomicBoolean(false); - private static final ILog LOGGER = LogManager.getLogger(EventPublishingStartedInterceptor.class); + private static final ILog LOGGER = LogManager.getLogger(EventPublishingStartedInterceptorV2.class); @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { @@ -61,7 +61,9 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA // Load Spring Properties SpringPropertiesLoader.loadSpringProperties(context.getEnvironment()); // register Dynamic ThreadPool Refresh Listener - AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener()); + if (AbstractSubjectCenter.get(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH) == null) { + AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener()); + } } return ret; diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/resources/hippo4j-plugin.def b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/resources/hippo4j-plugin.def index 8dad75eaf1..029e7955ff 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/resources/hippo4j-plugin.def +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-2x-plugin/src/main/resources/hippo4j-plugin.def @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -spring-boot-2.x=cn.hippo4j.agent.plugin.spring.boot.v2.define.EventPublishingRunListenerInstrumentation \ No newline at end of file +spring-boot-2.x=cn.hippo4j.agent.plugin.spring.boot.v2.define.EventPublishingRunListenerInstrumentationV2 \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/pom.xml b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/pom.xml new file mode 100644 index 0000000000..c3a32e47b7 --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + cn.hippo4j + hippo4j-agent-spring-plugins + ${revision} + + + hippo4j-agent-spring-boot-3x-plugin + + + 3.0.2 + + + + + + org.springframework.boot + spring-boot-starter + ${spring-boot.version} + provided + + + + cn.hippo4j + hippo4j-agent-spring-plugin-common + ${project.version} + + + + + \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/boot/SpringBootV3PluginBootService.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/boot/SpringBootV3PluginBootService.java new file mode 100644 index 0000000000..29cb0c2aab --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/boot/SpringBootV3PluginBootService.java @@ -0,0 +1,52 @@ +/* + * 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.agent.plugin.spring.boot.v3.boot; + +import cn.hippo4j.agent.core.boot.BootService; +import cn.hippo4j.agent.core.boot.DefaultImplementor; +import cn.hippo4j.common.logging.api.ILog; +import cn.hippo4j.common.logging.api.LogManager; + +/** + * SpringBoot v3 plugin boot service + */ +@DefaultImplementor +public class SpringBootV3PluginBootService implements BootService { + + private static final ILog LOGGER = LogManager.getLogger(SpringBootV3PluginBootService.class); + + @Override + public void prepare() throws Throwable { + + } + + @Override + public void boot() throws Throwable { + LOGGER.info("Loader SpringBootV3PluginBootService..."); + } + + @Override + public void onComplete() throws Throwable { + + } + + @Override + public void shutdown() throws Throwable { + + } +} diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/define/EventPublishingRunListenerInstrumentationV3.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/define/EventPublishingRunListenerInstrumentationV3.java new file mode 100644 index 0000000000..f5ee63cc05 --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/define/EventPublishingRunListenerInstrumentationV3.java @@ -0,0 +1,87 @@ +/* + * 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.agent.plugin.spring.boot.v3.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; +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 cn.hippo4j.agent.core.plugin.match.NameMatch.byName; +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * SpringBoot v3 Event publishing run listener instrumentation + */ +public class EventPublishingRunListenerInstrumentationV3 extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.boot.context.event.EventPublishingRunListener"; + + private static final String EVENT_PUBLISHING_STARTED_INTERCEPTOR_V3 = "cn.hippo4j.agent.plugin.spring.boot.v3.interceptor.EventPublishingStartedInterceptorV3"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + + @Override + public ElementMatcher getMethodsMatcher() { + return named("ready"); + } + + @Override + public String getMethodsInterceptor() { + return EVENT_PUBLISHING_STARTED_INTERCEPTOR_V3; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", + named("ready"))); + } + + @Override + protected String[] witnessClasses() { + return new String[]{"org.springframework.boot.context.properties.bind.ConstructorBinding"}; + } + +} diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/interceptor/EventPublishingStartedInterceptorV3.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/interceptor/EventPublishingStartedInterceptorV3.java new file mode 100644 index 0000000000..c4c02a0d66 --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v3/interceptor/EventPublishingStartedInterceptorV3.java @@ -0,0 +1,73 @@ +/* + * 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.agent.plugin.spring.boot.v3.interceptor; + +import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import cn.hippo4j.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import cn.hippo4j.agent.plugin.spring.common.event.DynamicThreadPoolRefreshListener; +import cn.hippo4j.agent.plugin.spring.common.support.SpringPropertiesLoader; +import cn.hippo4j.agent.plugin.spring.common.support.SpringThreadPoolRegisterSupport; +import cn.hippo4j.common.extension.design.AbstractSubjectCenter; +import cn.hippo4j.common.logging.api.ILog; +import cn.hippo4j.common.logging.api.LogManager; +import cn.hippo4j.core.config.ApplicationContextHolder; +import org.springframework.context.ConfigurableApplicationContext; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Event publishing started interceptor + */ +public class EventPublishingStartedInterceptorV3 implements InstanceMethodsAroundInterceptor { + + private static final AtomicBoolean isExecuted = new AtomicBoolean(false); + + private static final ILog LOGGER = LogManager.getLogger(EventPublishingStartedInterceptorV3.class); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + ConfigurableApplicationContext context = (ConfigurableApplicationContext) allArguments[0]; + // This logic will only be executed once + if (isExecuted.compareAndSet(false, true)) { + ApplicationContextHolder contextHolder = new ApplicationContextHolder(); + contextHolder.setApplicationContext(context); + // Load Spring Properties + SpringPropertiesLoader.loadSpringProperties(context.getEnvironment()); + // the thread pool registration will be carried out + SpringThreadPoolRegisterSupport.registerThreadPoolInstances(context); + // register Dynamic ThreadPool Refresh Listener + if (AbstractSubjectCenter.get(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH) == null) { + AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener()); + } + } + + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService new file mode 100644 index 0000000000..5685fd164c --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService @@ -0,0 +1,17 @@ +# 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. + +cn.hippo4j.agent.plugin.spring.boot.v3.boot.SpringBootV3PluginBootService \ No newline at end of file diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/resources/hippo4j-plugin.def b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/resources/hippo4j-plugin.def new file mode 100644 index 0000000000..7d27b3581e --- /dev/null +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-3x-plugin/src/main/resources/hippo4j-plugin.def @@ -0,0 +1,17 @@ +# 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. + +spring-boot-3.x=cn.hippo4j.agent.plugin.spring.boot.v3.define.EventPublishingRunListenerInstrumentationV3 diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/pom.xml b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/pom.xml index 94992b9505..5552d5e16a 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/pom.xml +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/pom.xml @@ -45,6 +45,12 @@ cn.hippo4j hippo4j-threadpool-kernel-alarm ${project.version} + + + org.springframework + spring-core + + cn.hippo4j @@ -57,10 +63,27 @@ + + cn.hippo4j + hippo4j-threadpool-dynamic-mode-config + ${project.version} + + + org.springframework + spring-core + + + cn.hippo4j hippo4j-threadpool-adapter-web ${project.version} + + + org.springframework.boot + spring-boot-starter + + cn.hippo4j diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/alarm/AgentModeNotifyConfigBuilder.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/alarm/AgentModeNotifyConfigBuilder.java index 9e8c1ce122..8a77f7d0c0 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/alarm/AgentModeNotifyConfigBuilder.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/alarm/AgentModeNotifyConfigBuilder.java @@ -29,7 +29,6 @@ import cn.hippo4j.threadpool.message.api.NotifyConfigBuilder; import cn.hippo4j.threadpool.message.api.NotifyConfigDTO; import cn.hippo4j.threadpool.message.core.service.AlarmControlHandler; -import cn.hippo4j.threadpool.message.core.service.ThreadPoolBaseSendMessageService; import lombok.AllArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/interceptor/EventPublishingRunListenerEnvironmentPreparedInterceptor.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/interceptor/EventPublishingRunListenerEnvironmentPreparedInterceptor.java index 2b70e22ac8..e148c96bea 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/interceptor/EventPublishingRunListenerEnvironmentPreparedInterceptor.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/interceptor/EventPublishingRunListenerEnvironmentPreparedInterceptor.java @@ -26,12 +26,15 @@ import org.springframework.core.env.ConfigurableEnvironment; import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicBoolean; /** * Event publishing run listener environment prepared interceptor */ public class EventPublishingRunListenerEnvironmentPreparedInterceptor implements InstanceMethodsAroundInterceptor { + private static final AtomicBoolean isExecuted = new AtomicBoolean(false); + private static final Logger LOGGER = LoggerFactory.getLogger(EventPublishingRunListenerEnvironmentPreparedInterceptor.class); @Override @@ -41,9 +44,16 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - ConfigurableEnvironment environment = (ConfigurableEnvironment) allArguments[0]; - SpringEnvironmentSupport.disableNonAgentSwitch(environment); - LOGGER.info("[Hippo4j-Agent] Switch off in non-Agent mode."); + if (isExecuted.compareAndSet(false, true)) { + ConfigurableEnvironment environment = null; + try { + environment = (ConfigurableEnvironment) allArguments[0]; + } catch (Exception e) { + environment = (ConfigurableEnvironment) allArguments[1]; + } + SpringEnvironmentSupport.disableNonAgentSwitch(environment); + LOGGER.info("[Hippo4j-Agent] Switch off in non-Agent mode."); + } return ret; } diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringThreadPoolRegisterSupport.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringThreadPoolRegisterSupport.java index 2af5a280d6..4aba9498f8 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringThreadPoolRegisterSupport.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringThreadPoolRegisterSupport.java @@ -28,11 +28,11 @@ import cn.hippo4j.common.toolkit.ThreadPoolExecutorUtil; import cn.hippo4j.threadpool.dynamic.mode.config.properties.BootstrapConfigProperties; import cn.hippo4j.threadpool.message.core.service.GlobalNotifyAlarmManage; - import cn.hippo4j.threadpool.message.core.service.ThreadPoolNotifyAlarm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -83,21 +83,27 @@ public static void registerThreadPoolInstances(ApplicationContext context) { } Map beansWithAnnotation = context.getBeansOfType(Executor.class); - for (Map.Entry entry : beansWithAnnotation.entrySet()) { - String beanName = entry.getKey(); - Executor bean = entry.getValue(); - ThreadPoolExecutor executor; + beansWithAnnotation.forEach((beanName, bean) -> { + ThreadPoolExecutor executor = null; + // Get ThreadPoolExecutor Instance if (DynamicThreadPoolAdapterChoose.match(bean)) { executor = DynamicThreadPoolAdapterChoose.unwrap(bean); - } else { + } else if (bean instanceof ThreadPoolTaskExecutor) { + ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) bean; + // Get a real instance of ThreadPoolExecutor + executor = taskExecutor.getThreadPoolExecutor(); + } else if (bean instanceof ThreadPoolExecutor) { executor = (ThreadPoolExecutor) bean; + } else { + LOGGER.warn("[Hippo4j-Agent] Thread pool ignore registered beanName={}, Now Unsupported thread pool executor type:{} ", beanName, bean.getClass().getName()); } if (executor == null) { LOGGER.warn("[Hippo4j-Agent] Thread pool is null, ignore bean registration. beanName={}, beanClass={}", beanName, bean.getClass().getName()); } else { register(beanName, executor, Boolean.FALSE); } - } + }); + LOGGER.info("[Hippo4j-Agent] Registered thread pool instances successfully."); } @@ -105,10 +111,8 @@ public static void register(String threadPoolId, ThreadPoolExecutor executor, Bo if (executor == null) { return; } - ExecutorProperties executorProperties = SpringPropertiesLoader.BOOTSTRAP_CONFIG_PROPERTIES.getExecutors().stream() - .filter(each -> Objects.equals(threadPoolId, each.getThreadPoolId())) - .findFirst() - .orElse(null); + ExecutorProperties executorProperties = + SpringPropertiesLoader.BOOTSTRAP_CONFIG_PROPERTIES.getExecutors().stream().filter(each -> Objects.equals(threadPoolId, each.getThreadPoolId())).findFirst().orElse(null); // Determines the thread pool that is currently obtained by bean scanning if (Objects.isNull(executorProperties)) { @@ -198,16 +202,13 @@ private static ExecutorProperties buildExecutorProperties(ExecutorProperties exe .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getRejectedHandler).get())) .threadNamePrefix(StringUtil.isBlank(executorProperties.getThreadNamePrefix()) ? executorProperties.getThreadPoolId() : executorProperties.getThreadNamePrefix()) .threadPoolId(executorProperties.getThreadPoolId()) - .alarm(Optional.ofNullable(executorProperties.getAlarm()) - .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getAlarm).orElse(null))) + .alarm(Optional.ofNullable(executorProperties.getAlarm()).orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getAlarm).orElse(null))) .activeAlarm(Optional.ofNullable(executorProperties.getActiveAlarm()) .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getActiveAlarm).orElse(null))) .capacityAlarm(Optional.ofNullable(executorProperties.getCapacityAlarm()) .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getCapacityAlarm).orElse(null))) - .notify(Optional.ofNullable(executorProperties.getNotify()) - .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getNotify).orElse(null))) - .nodes(Optional.ofNullable(executorProperties.getNodes()) - .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getNodes).orElse(null))) + .notify(Optional.ofNullable(executorProperties.getNotify()).orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getNotify).orElse(null))) + .nodes(Optional.ofNullable(executorProperties.getNodes()).orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getNodes).orElse(null))) .build(); } @@ -220,17 +221,14 @@ private static ExecutorProperties buildExecutorProperties(ExecutorProperties exe private static ThreadPoolNotifyAlarm buildThreadPoolNotifyAlarm(ExecutorProperties executorProperties) { BootstrapConfigProperties configProperties = SpringPropertiesLoader.BOOTSTRAP_CONFIG_PROPERTIES; ExecutorNotifyProperties notify = Optional.ofNullable(executorProperties).map(ExecutorProperties::getNotify).orElse(null); - boolean isAlarm = Optional.ofNullable(executorProperties.getAlarm()) - .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getAlarm).orElse(true)); + boolean isAlarm = Optional.ofNullable(executorProperties.getAlarm()).orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getAlarm).orElse(true)); int activeAlarm = Optional.ofNullable(executorProperties.getActiveAlarm()) .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getActiveAlarm).orElse(DEFAULT_ACTIVE_ALARM)); int capacityAlarm = Optional.ofNullable(executorProperties.getCapacityAlarm()) .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getCapacityAlarm).orElse(DEFAULT_CAPACITY_ALARM)); - int interval = Optional.ofNullable(notify) - .map(ExecutorNotifyProperties::getInterval) + int interval = Optional.ofNullable(notify).map(ExecutorNotifyProperties::getInterval) .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getNotify).map(ExecutorNotifyProperties::getInterval).orElse(DEFAULT_INTERVAL)); - String receive = Optional.ofNullable(notify) - .map(ExecutorNotifyProperties::getReceives) + String receive = Optional.ofNullable(notify).map(ExecutorNotifyProperties::getReceives) .orElseGet(() -> Optional.ofNullable(configProperties.getDefaultExecutor()).map(ExecutorProperties::getNotify).map(ExecutorNotifyProperties::getReceives).orElse(DEFAULT_RECEIVES)); ThreadPoolNotifyAlarm threadPoolNotifyAlarm = new ThreadPoolNotifyAlarm(isAlarm, activeAlarm, capacityAlarm); threadPoolNotifyAlarm.setInterval(interval); diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolCheckAlarmSupport.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolCheckAlarmSupport.java index 955f3bdbfd..58cd213148 100644 --- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolCheckAlarmSupport.java +++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolCheckAlarmSupport.java @@ -93,6 +93,9 @@ public static void enableThreadPoolCheckAlarmHandler() { // Execute scheduled task to check an alarm scheduleExecute(threadPoolBaseSendMessageService); + + LOGGER.info("[Hippo4j-Agent] Start Check AlarmHandler the running status of dynamic thread pools."); + } } diff --git a/agent/pom.xml b/agent/pom.xml index 18de9269a2..4f7c0abbd5 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -23,7 +23,7 @@ 4.13.1 2.0.7 3.5.13 - 1.18.20 + 1.18.34 1.12.13 diff --git a/examples/threadpool-example/agent/agent-example-core/pom.xml b/examples/threadpool-example/agent/agent-example-core/pom.xml index 3feb4a56fd..c43cb21a63 100644 --- a/examples/threadpool-example/agent/agent-example-core/pom.xml +++ b/examples/threadpool-example/agent/agent-example-core/pom.xml @@ -6,7 +6,7 @@ cn.hippo4j hippo4j-threadpool-agent-example - 2.0.0-SNAPSHOT + ${revision} hippo4j-agent-example-core diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-1x/pom.xml b/examples/threadpool-example/agent/config-apollo-spring-boot-1x/pom.xml index 6277fad0ac..9c579ad034 100644 --- a/examples/threadpool-example/agent/config-apollo-spring-boot-1x/pom.xml +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-1x/pom.xml @@ -6,7 +6,7 @@ cn.hippo4j hippo4j-threadpool-agent-example - 2.0.0-SNAPSHOT + ${revision} hippo4j-threadpool-agent-config-apollo-spring-boot-1x diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/apollo/v1/AgentConfigApolloSpringBoot1xExampleApplication.java b/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/apollo/v1/AgentConfigApolloSpringBoot1xExampleApplication.java index 26896afd21..9ad3b62331 100644 --- a/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/apollo/v1/AgentConfigApolloSpringBoot1xExampleApplication.java +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/apollo/v1/AgentConfigApolloSpringBoot1xExampleApplication.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Agent config Nacos example application. + * Agent config Apollo Spring Boot 1.x example application. */ @SpringBootApplication(scanBasePackages = "cn.hippo4j.example.agent.core") public class AgentConfigApolloSpringBoot1xExampleApplication { diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-3x/pom.xml b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/pom.xml new file mode 100644 index 0000000000..e8221449b5 --- /dev/null +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/pom.xml @@ -0,0 +1,92 @@ + + + 4.0.0 + + cn.hippo4j + hippo4j-threadpool-agent-example + 2.0.0-SNAPSHOT + + + hippo4j-threadpool-agent-config-apollo-spring-boot-3x + + + true + 3.0.2 + 17 + 17 + 17 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + cn.hippo4j + hippo4j-agent-example-core + ${revision} + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.ctrip.framework.apollo + apollo-client + 2.3.0 + + + + org.springframework.cloud + spring-cloud-context + 4.1.4 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 3.3.4 + + + + repackage + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + + + + + + \ No newline at end of file diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/AgentConfigApolloSpringBoot3xExampleApplication.java b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/AgentConfigApolloSpringBoot3xExampleApplication.java new file mode 100644 index 0000000000..3bbd562ea9 --- /dev/null +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/AgentConfigApolloSpringBoot3xExampleApplication.java @@ -0,0 +1,33 @@ +/* + * 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.example.agent.config.apollo.v3; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Agent config Apollo boot3 example application. + */ +@SpringBootApplication(scanBasePackages = "cn.hippo4j.example.agent.config.apollo.v3") +public class AgentConfigApolloSpringBoot3xExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(AgentConfigApolloSpringBoot3xExampleApplication.class, args); + } + +} diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/AlarmSendMessageBootV3Test.java b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/AlarmSendMessageBootV3Test.java new file mode 100644 index 0000000000..8a6a23cdd4 --- /dev/null +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/AlarmSendMessageBootV3Test.java @@ -0,0 +1,87 @@ +/* + * 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.example.agent.config.apollo.v3; + +import cn.hippo4j.common.executor.ThreadPoolExecutorHolder; +import cn.hippo4j.common.executor.ThreadPoolExecutorRegistry; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Test alarm send message. + */ +@Slf4j +@Component +public class AlarmSendMessageBootV3Test { + + private static final int SLEEP_TIME = 10240124; + + private static final int INITIAL_DELAY = 3; + + private static final String RUN_MESSAGE_SEND_TASK_EXECUTOR = "runMessageSendTaskExecutor"; + + private static final String AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR = "cn.hippo4j.example.agent.config.apollo.v3.ThreadPoolConfigurationBootV3#AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR"; + + /** + * Test alarm notification. + * If you need to run this single test, add @PostConstruct to the method. + */ + @SuppressWarnings("all") + // @PostConstruct + public void alarmSendMessageTest() { + ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor(); + scheduledThreadPool.scheduleWithFixedDelay(() -> { + ThreadPoolExecutorHolder executorHolder = ThreadPoolExecutorRegistry.getHolder(AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR); + ThreadPoolExecutor poolExecutor = executorHolder.getExecutor(); + try { + poolExecutor.execute(() -> { + try { + Thread.sleep(SLEEP_TIME); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ex) { + log.error("Throw reject policy.", ex.getMessage()); + } + }, INITIAL_DELAY, 2, TimeUnit.SECONDS); + + scheduledThreadPool.scheduleWithFixedDelay(() -> { + ThreadPoolExecutorHolder executorHolder = ThreadPoolExecutorRegistry.getHolder(RUN_MESSAGE_SEND_TASK_EXECUTOR); + ThreadPoolExecutor poolExecutor = executorHolder.getExecutor(); + try { + poolExecutor.execute(() -> { + try { + Thread.sleep(SLEEP_TIME); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ex) { + log.error("Throw reject policy.", ex.getMessage()); + } + }, INITIAL_DELAY, 2, TimeUnit.SECONDS); + + } +} diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/ThreadPoolConfigurationBootV3.java b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/ThreadPoolConfigurationBootV3.java new file mode 100644 index 0000000000..16320a455a --- /dev/null +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/apollo/v3/ThreadPoolConfigurationBootV3.java @@ -0,0 +1,55 @@ +/* + * 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.example.agent.config.apollo.v3; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Configuration +public class ThreadPoolConfigurationBootV3 { + + // ------------------------------------------------------------------------- + // 未使用 Hippo4j,原始定义线程池创建方式 + // ------------------------------------------------------------------------- + + @Bean + public ThreadPoolExecutor runMessageSendTaskExecutor() { + LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue<>(1024); + return new ThreadPoolExecutor( + 1, + 10, + 1024, + TimeUnit.SECONDS, + linkedBlockingQueue); + } + + // ------------------------------------------------------------------------- + // 演示 Agent 模式修改线程池 + // ------------------------------------------------------------------------- + + public static final ThreadPoolExecutor AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR = new ThreadPoolExecutor( + 1, + 10, + 1024, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(1024)); +} diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/resources/application.properties b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/resources/application.properties new file mode 100644 index 0000000000..b8c971daca --- /dev/null +++ b/examples/threadpool-example/agent/config-apollo-spring-boot-3x/src/main/resources/application.properties @@ -0,0 +1,66 @@ +server.port=8092 +server.servlet.context-path=/example + +app.id=dynamic-threadpool-example-springboot3-test +apollo.meta=http://127.0.0.1:8080 +apollo.autoUpdateInjectedSpringProperties=true +apollo.bootstrap.enabled=true +apollo.bootstrap.namespaces=application +apollo.bootstrap.eagerLoad.enabled=true + +# The following parameters are used for testing +env=dev +apollo.configService=http://127.0.0.1:8080 +spring.profiles.active=dev +spring.application.name=hippo4j-config-apollo-spring-boot-starter-example + +spring.dynamic.thread-pool.enable=true +spring.dynamic.thread-pool.banner=true +spring.dynamic.thread-pool.check-state-interval=10 +spring.dynamic.thread-pool.monitor.enable=true +spring.dynamic.thread-pool.monitor.collect-types=micrometer +spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic +spring.dynamic.thread-pool.monitor.initial-delay=3000 +spring.dynamic.thread-pool.monitor.collect-interval=3000 +spring.dynamic.thread-pool.monitor.agent-micrometer-port=29999 + +spring.dynamic.thread-pool.notify-platforms[0].platform=LARK +spring.dynamic.thread-pool.notify-platforms[0].token=6de41bdc-0799-45be-b128-7cddb9e777f0 +#spring.dynamic.thread-pool.notify-platforms[1].platform=WECHAT +#spring.dynamic.thread-pool.notify-platforms[1].token=ac0426a5-c712-474c-9bff-72b8b8f5caff +#spring.dynamic.thread-pool.notify-platforms[2].platform=DING +#spring.dynamic.thread-pool.notify-platforms[2].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55 + +spring.dynamic.thread-pool.apollo.namespace=application +spring.dynamic.thread-pool.config-file-type=properties + +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].thread-pool-id = cn.hippo4j.example.agent.config.apollo.v3.ThreadPoolConfigurationBootV3#AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR +spring.dynamic.thread-pool.executors[0].maximum-pool-size = 20 +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 = nobodyiam + +spring.dynamic.thread-pool.executors[1].thread-pool-id = runMessageSendTaskExecutor +spring.dynamic.thread-pool.executors[1].thread-name-prefix = runMessageSendTaskExecutor +spring.dynamic.thread-pool.executors[1].core-pool-size = 3 +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].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 = nobodyiam diff --git a/examples/threadpool-example/agent/config-apollo/src/main/java/cn/hippo4j/example/agent/config/apollo/AgentConfigApolloExampleApplication.java b/examples/threadpool-example/agent/config-apollo/src/main/java/cn/hippo4j/example/agent/config/apollo/AgentConfigApolloExampleApplication.java index 365282b7b3..8879f503a6 100644 --- a/examples/threadpool-example/agent/config-apollo/src/main/java/cn/hippo4j/example/agent/config/apollo/AgentConfigApolloExampleApplication.java +++ b/examples/threadpool-example/agent/config-apollo/src/main/java/cn/hippo4j/example/agent/config/apollo/AgentConfigApolloExampleApplication.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Agent config apollo example application. + * Agent Apollo Spring Boot 2.x example application. */ @SpringBootApplication(scanBasePackages = "cn.hippo4j.example.agent.core") public class AgentConfigApolloExampleApplication { diff --git a/examples/threadpool-example/agent/config-naocs-spring-boot-3x/pom.xml b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/pom.xml new file mode 100644 index 0000000000..41282d6e4f --- /dev/null +++ b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/pom.xml @@ -0,0 +1,98 @@ + + + 4.0.0 + + cn.hippo4j + hippo4j-threadpool-agent-example + 2.0.0-SNAPSHOT + + + hippo4j-threadpool-agent-config-nacos-spring-boot-3x + + + true + 3.0.2 + 17 + 17 + 17 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + cn.hippo4j + hippo4j-agent-example-core + ${revision} + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + 2022.0.0.0-RC2 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework + spring-core + 6.0.4 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 3.3.4 + + + + repackage + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + + + + + + + \ No newline at end of file diff --git a/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/AgentConfigNacosSpringBoot3xExampleApplication.java b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/AgentConfigNacosSpringBoot3xExampleApplication.java new file mode 100644 index 0000000000..d6397c0c26 --- /dev/null +++ b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/AgentConfigNacosSpringBoot3xExampleApplication.java @@ -0,0 +1,32 @@ +/* + * 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.example.agent.config.nacos.v3; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Agent config Nacos boot3 example application. + */ +@SpringBootApplication(scanBasePackages = "cn.hippo4j.example.agent.config.nacos.v3") +public class AgentConfigNacosSpringBoot3xExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(AgentConfigNacosSpringBoot3xExampleApplication.class, args); + } +} diff --git a/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/AlarmSendMessageBootV3Test.java b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/AlarmSendMessageBootV3Test.java new file mode 100644 index 0000000000..68da590c3e --- /dev/null +++ b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/AlarmSendMessageBootV3Test.java @@ -0,0 +1,87 @@ +/* + * 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.example.agent.config.nacos.v3; + +import cn.hippo4j.common.executor.ThreadPoolExecutorHolder; +import cn.hippo4j.common.executor.ThreadPoolExecutorRegistry; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Test alarm send message. + */ +@Slf4j +@Component +public class AlarmSendMessageBootV3Test { + + private static final int SLEEP_TIME = 10240124; + + private static final int INITIAL_DELAY = 3; + + private static final String RUN_MESSAGE_SEND_TASK_EXECUTOR = "runMessageSendTaskExecutor"; + + private static final String AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR = "cn.hippo4j.example.agent.config.nacos.v3.ThreadPoolConfigurationBootV3#AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR"; + + /** + * Test alarm notification. + * If you need to run this single test, add @PostConstruct to the method. + */ + @SuppressWarnings("all") + //@PostConstruct + public void alarmSendMessageTest() { + ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor(); + scheduledThreadPool.scheduleWithFixedDelay(() -> { + ThreadPoolExecutorHolder executorHolder = ThreadPoolExecutorRegistry.getHolder(AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR); + ThreadPoolExecutor poolExecutor = executorHolder.getExecutor(); + try { + poolExecutor.execute(() -> { + try { + Thread.sleep(SLEEP_TIME); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ex) { + log.error("Throw reject policy.", ex.getMessage()); + } + }, INITIAL_DELAY, 2, TimeUnit.SECONDS); + + scheduledThreadPool.scheduleWithFixedDelay(() -> { + ThreadPoolExecutorHolder executorHolder = ThreadPoolExecutorRegistry.getHolder(RUN_MESSAGE_SEND_TASK_EXECUTOR); + ThreadPoolExecutor poolExecutor = executorHolder.getExecutor(); + try { + poolExecutor.execute(() -> { + try { + Thread.sleep(SLEEP_TIME); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); + } catch (Exception ex) { + log.error("Throw reject policy.", ex.getMessage()); + } + }, INITIAL_DELAY, 2, TimeUnit.SECONDS); + + } +} diff --git a/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/ThreadPoolConfigurationBootV3.java b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/ThreadPoolConfigurationBootV3.java new file mode 100644 index 0000000000..88cdc8fbde --- /dev/null +++ b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/java/cn/hippo4j/example/agent/config/nacos/v3/ThreadPoolConfigurationBootV3.java @@ -0,0 +1,55 @@ +/* + * 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.example.agent.config.nacos.v3; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Configuration +public class ThreadPoolConfigurationBootV3 { + + // ------------------------------------------------------------------------- + // 未使用 Hippo4j,原始定义线程池创建方式 + // ------------------------------------------------------------------------- + + @Bean + public ThreadPoolExecutor runMessageSendTaskExecutor() { + LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue<>(1024); + return new ThreadPoolExecutor( + 1, + 10, + 1024, + TimeUnit.SECONDS, + linkedBlockingQueue); + } + + // ------------------------------------------------------------------------- + // 演示 Agent 模式修改线程池 + // ------------------------------------------------------------------------- + + public static final ThreadPoolExecutor AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR = new ThreadPoolExecutor( + 1, + 10, + 1024, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(1024)); +} diff --git a/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/resources/application.properties b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/resources/application.properties new file mode 100644 index 0000000000..b2940dbfb7 --- /dev/null +++ b/examples/threadpool-example/agent/config-naocs-spring-boot-3x/src/main/resources/application.properties @@ -0,0 +1,76 @@ +server.port=8093 +server.servlet.context-path=/example + +# The following parameters are used for testing + +# NacosCloud properties +spring.cloud.nacos.config.server-addr=127.0.0.1:8848 +# boot3 version nacosCloud must add , In order to refresh configuration to Env +spring.config.import=nacos:dynamic-threadpool-example-config-boot3?refreshEnabled=true + +# NacosBoot properties +#nacos.config.auto-refresh=true +#nacos.config.bootstrap.enable=true +#nacos.config.server-addr=127.0.0.1:8848 +#nacos.config.data-id=dynamic-threadpool-example-config-boot3 +#nacos.config.group=DEFAULT_GROUP +#nacos.config.type=properties + +spring.profiles.active=dev +spring.application.name=hippo4j-config-nacos-spring-boot-starter-example +management.metrics.export.prometheus.enabled=true +management.server.port=29998 +management.endpoints.web.exposure.include=* +spring.dynamic.thread-pool.enable=true +spring.dynamic.thread-pool.banner=true +spring.dynamic.thread-pool.check-state-interval=10 +#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.agent-micrometer-port=29999 + +spring.dynamic.thread-pool.monitor.initial-delay=3000 +spring.dynamic.thread-pool.monitor.collect-interval=3000 +spring.dynamic.thread-pool.notify-platforms[0].platform=LARK +spring.dynamic.thread-pool.notify-platforms[0].token=6de41bdc-0799-45be-b128-7cddb9e777f0 +#spring.dynamic.thread-pool.notify-platforms[1].platform=WECHAT +#spring.dynamic.thread-pool.notify-platforms[1].token=ac0426a5-c712-474c-9bff-72b8b8f5caff +#spring.dynamic.thread-pool.notify-platforms[2].platform=DING +#spring.dynamic.thread-pool.notify-platforms[2].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55 + +spring.dynamic.thread-pool.nacos.data-id=dynamic-threadpool-example-config-boot3 +spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP +spring.dynamic.thread-pool.nacos.namespace=public + +spring.dynamic.thread-pool.config-file-type=properties + +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].thread-pool-id =cn.hippo4j.example.agent.config.nacos.v3.ThreadPoolConfigurationBootV3#AGENT_RUN_MESSAGE_SEND_TASK_EXECUTOR +spring.dynamic.thread-pool.executors[0].maximum-pool-size = 20 +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 = nobodyiam + +spring.dynamic.thread-pool.executors[1].thread-pool-id = runMessageSendTaskExecutor +spring.dynamic.thread-pool.executors[1].thread-name-prefix = runMessageSendTaskExecutor +spring.dynamic.thread-pool.executors[1].core-pool-size = 3 +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].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 = nobodyiam diff --git a/examples/threadpool-example/agent/pom.xml b/examples/threadpool-example/agent/pom.xml index fcbe2ce272..305226ba36 100644 --- a/examples/threadpool-example/agent/pom.xml +++ b/examples/threadpool-example/agent/pom.xml @@ -22,5 +22,8 @@ agent-example-core config-nacos-spring-boot-1x config-apollo-spring-boot-1x + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6237e82f19..b6dff1a577 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 0.8.8 UTF-8 UTF-8 - 3.6.1 + 3.12.1 3.0.0 3.0.1 3.0.2 @@ -79,10 +79,16 @@ 3.1.0 2.3.2.RELEASE 2.8.9 + 1.18.34 + + org.projectlombok + lombok + ${lombok.version} + cn.hippo4j hippo4j-dependencies @@ -126,6 +132,7 @@ org.apache.maven.plugins maven-jar-plugin + ${maven.jar.plugin.version} diff --git a/starters/threadpool/config/src/main/java/cn/hippo4j/config/springboot/starter/refresher/AbstractConfigThreadPoolDynamicRefresh.java b/starters/threadpool/config/src/main/java/cn/hippo4j/config/springboot/starter/refresher/AbstractConfigThreadPoolDynamicRefresh.java index 79fa51abdc..b956d6170d 100644 --- a/starters/threadpool/config/src/main/java/cn/hippo4j/config/springboot/starter/refresher/AbstractConfigThreadPoolDynamicRefresh.java +++ b/starters/threadpool/config/src/main/java/cn/hippo4j/config/springboot/starter/refresher/AbstractConfigThreadPoolDynamicRefresh.java @@ -75,7 +75,6 @@ private void publishDynamicThreadPoolEvent(BootstrapConfigProperties configPrope ApplicationContextHolder.getInstance().publishEvent(new ThreadPoolConfigDynamicRefreshEvent(this, configProperties)); } - @Override public void run(ApplicationArguments args) { try {