diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml b/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml
new file mode 100644
index 00000000..f048923f
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+
+ cn.hippo4j
+ hippo4j-agent-plugin
+ ${revision}
+
+
+ hippo4j-agent-nacos-plugin
+
+
+ 2.2.1
+
+
+
+
+ cn.hippo4j
+ hippo4j-agent-spring-plugin-common
+ ${project.version}
+
+
+ cn.hippo4j
+ hippo4j-threadpool-dynamic-mode-config
+ ${project.version}
+
+
+ com.alibaba.nacos
+ nacos-client
+ ${nacos.version}
+ provided
+
+
+
+
\ No newline at end of file
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
new file mode 100644
index 00000000..866f3ccc
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/NacosDynamicThreadPoolChangeHandler.java
@@ -0,0 +1,129 @@
+/*
+ * 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.nacos;
+
+import cn.hippo4j.agent.plugin.spring.common.conf.SpringBootConfig;
+import cn.hippo4j.agent.plugin.spring.common.toolkit.SpringPropertyBinder;
+import cn.hippo4j.common.executor.ThreadFactoryBuilder;
+import cn.hippo4j.common.logging.api.ILog;
+import cn.hippo4j.common.logging.api.LogManager;
+import cn.hippo4j.threadpool.dynamic.mode.config.parser.ConfigParserHandler;
+import cn.hippo4j.threadpool.dynamic.mode.config.properties.BootstrapConfigProperties;
+import cn.hippo4j.threadpool.dynamic.mode.config.refresher.AbstractConfigThreadPoolDynamicRefresh;
+import com.alibaba.nacos.api.NacosFactory;
+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;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+import static cn.hippo4j.common.constant.Constants.DEFAULT_NAMESPACE_ID;
+
+/**
+ * NacosDynamicThreadPoolChangeHandler is responsible for handling dynamic thread pool
+ * configuration changes in a Spring environment by listening to configuration updates from Nacos.
+ *
+ * This class extends {@link AbstractConfigThreadPoolDynamicRefresh} and implements the logic
+ * to register a Nacos listener, handle configuration changes, and dynamically refresh the thread pool
+ * properties based on the new configuration.
+ *
+ */
+public class NacosDynamicThreadPoolChangeHandler extends AbstractConfigThreadPoolDynamicRefresh {
+
+ private static final ILog LOGGER = LogManager.getLogger(NacosDynamicThreadPoolChangeHandler.class);
+
+ /**
+ * Registers a listener with Nacos to monitor for changes in the thread pool configuration.
+ *
+ * This method sets up the Nacos {@link ConfigService} with the server address and namespace
+ * from the Spring Boot configuration. It then adds a listener that will receive and process
+ * configuration updates, triggering a dynamic refresh of thread pool settings.
+ */
+ @Override
+ public void registerListener() {
+ // Retrieve necessary configuration properties
+ String configFileType = SpringBootConfig.Spring.Dynamic.Thread_Pool.CONFIG_FILE_TYPE;
+ String serverAddr = SpringBootConfig.Spring.Dynamic.Thread_Pool.Nacos.SERVER_ADDR;
+ String dataId = SpringBootConfig.Spring.Dynamic.Thread_Pool.Nacos.DATA_ID;
+ String group = SpringBootConfig.Spring.Dynamic.Thread_Pool.Nacos.GROUP;
+ String namespace = SpringBootConfig.Spring.Dynamic.Thread_Pool.Nacos.NAMESPACE.get(0);
+ namespace = namespace.equals(DEFAULT_NAMESPACE_ID) ? "" : namespace;
+ try {
+ // Initialize Nacos ConfigService with the provided properties
+ Properties properties = new Properties();
+ properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
+ properties.put(PropertyKeyConst.NAMESPACE, namespace);
+ ConfigService configService = NacosFactory.createConfigService(properties);
+
+ // Define the listener to handle configuration changes
+ Listener configChangeListener = new Listener() {
+
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ LOGGER.debug("Received configuration: " + configInfo);
+ Map changeValueMap = new HashMap<>();
+ try {
+ // Parse the configuration and map the values to the appropriate keys
+ Map configInfoMap = ConfigParserHandler.getInstance().parseConfig(configInfo, configFileType);
+ configInfoMap.forEach((key, value) -> {
+ if (key instanceof String) {
+ changeValueMap.put((String) key, value);
+ }
+ });
+ } catch (IOException e) {
+ LOGGER.error(e, "[Hippo4j-Agent] Dynamic thread pool refresher, Failed to resolve configuration. configFileType: {} configInfo: {} ", configFileType, configInfo);
+ }
+ // Trigger the dynamic refresh with the parsed configuration
+ dynamicRefresh(configFileType, configInfo, changeValueMap);
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return new ScheduledThreadPoolExecutor(1, ThreadFactoryBuilder.builder().daemon(true).prefix("client.dynamic.refresh.agent").build());
+ }
+ };
+ // Add the listener to the Nacos ConfigService
+ configService.addListener(dataId, group, configChangeListener);
+ LOGGER.info("[Hippo4j-Agent] Dynamic thread pool refresher, add Nacos listener successfully. namespace: {} data-id: {} group: {}", namespace, dataId, group);
+ } catch (Exception e) {
+ LOGGER.error(e, "[Hippo4j-Agent] Dynamic thread pool refresher, add Nacos listener failure. namespace: {} data-id: {} group: {}", namespace, dataId, group);
+ }
+ }
+
+ /**
+ * 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
+ * of {@link BootstrapConfigProperties}, which can then be used to configure the thread pool
+ * dynamically.
+ *
+ * @param configInfo the configuration map containing properties to bind.
+ * @return the bound {@link BootstrapConfigProperties} instance.
+ */
+ @Override
+ public BootstrapConfigProperties buildBootstrapProperties(Map configInfo) {
+ BootstrapConfigProperties bindableBootstrapConfigProperties = SpringPropertyBinder.bindProperties(configInfo, BootstrapConfigProperties.PREFIX, BootstrapConfigProperties.class);
+ return bindableBootstrapConfigProperties;
+ }
+}
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/boot/NacosPluginBootService.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/boot/NacosPluginBootService.java
new file mode 100644
index 00000000..65fe2a47
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/boot/NacosPluginBootService.java
@@ -0,0 +1,48 @@
+/*
+ * 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.nacos.boot;
+
+import cn.hippo4j.agent.core.boot.BootService;
+import cn.hippo4j.agent.core.boot.DefaultImplementor;
+
+/**
+ * Nacos plugin boot service
+ */
+@DefaultImplementor
+public class NacosPluginBootService implements BootService {
+
+ @Override
+ public void prepare() throws Throwable {
+
+ }
+
+ @Override
+ public void boot() throws Throwable {
+
+ }
+
+ @Override
+ public void onComplete() throws Throwable {
+
+ }
+
+ @Override
+ public void shutdown() throws Throwable {
+
+ }
+}
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/define/NacosCloudAdapterInstrumentation.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/define/NacosCloudAdapterInstrumentation.java
new file mode 100644
index 00000000..6fe99477
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/define/NacosCloudAdapterInstrumentation.java
@@ -0,0 +1,75 @@
+/*
+ * 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.nacos.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 cn.hippo4j.agent.core.plugin.match.NameMatch;
+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;
+
+public class NacosCloudAdapterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ private static final String ENHANCE_CLASS = "org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration";
+
+ private static final String INSTANCE_METHODS_INTERCEPT_CLASS = "cn.hippo4j.agent.plugin.nacos.interceptor.NacosCloudAdapterConfigInstanceMethodInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return NameMatch.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("initialize");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return INSTANCE_METHODS_INTERCEPT_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }};
+ }
+
+ @Override
+ protected List witnessMethods() {
+ return Collections.singletonList(new WitnessMethod("com.alibaba.cloud.nacos.client.NacosPropertySourceLocator", named("locate")));
+ }
+}
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/define/NacosInstrumentation.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/define/NacosInstrumentation.java
new file mode 100644
index 00000000..d33c6031
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/define/NacosInstrumentation.java
@@ -0,0 +1,66 @@
+/*
+ * 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.nacos.define;
+
+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 cn.hippo4j.agent.core.plugin.match.NameMatch;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+
+/**
+ * Nacos instrumentation
+ */
+public class NacosInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ private static final String ENHANCE_CLASS = "com.alibaba.nacos.client.config.NacosConfigService";
+
+ private static final String CONSTRUCTOR_INTERCEPT_CLASS = "cn.hippo4j.agent.plugin.nacos.interceptor.NacosConfigConstructorInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return NameMatch.byName(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[]{
+ new ConstructorInterceptPoint() {
+
+ @Override
+ public ElementMatcher getConstructorMatcher() {
+ return any();
+ }
+
+ @Override
+ public String getConstructorInterceptor() {
+ return CONSTRUCTOR_INTERCEPT_CLASS;
+ }
+ }
+ };
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[0];
+ }
+}
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosCloudAdapterConfigInstanceMethodInterceptor.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosCloudAdapterConfigInstanceMethodInterceptor.java
new file mode 100644
index 00000000..7a7cf841
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosCloudAdapterConfigInstanceMethodInterceptor.java
@@ -0,0 +1,68 @@
+/*
+ * 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.nacos.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.support.SpringPropertiesLoader;
+import cn.hippo4j.agent.plugin.spring.common.support.SpringThreadPoolRegisterSupport;
+import cn.hippo4j.core.config.ApplicationContextHolder;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Nacos Cloud config constructor interceptor
+ */
+public class NacosCloudAdapterConfigInstanceMethodInterceptor implements InstanceMethodsAroundInterceptor {
+
+ private static final AtomicBoolean isExecuted = new AtomicBoolean(false);
+
+ @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 {
+ // This logic will only be executed once
+ if (isExecuted.compareAndSet(false, true)) {
+ // Get the configurable Application Context
+ ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) allArguments[0];
+ ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
+
+ // Remote Nacos configuration swiped into SpringPropertiesLoader
+ SpringPropertiesLoader.loadSpringProperties(environment);
+ // Refresh thread pool instances through configuration
+ SpringThreadPoolRegisterSupport.registerThreadPoolInstances(ApplicationContextHolder.getInstance());
+
+ }
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Throwable t) {
+
+ }
+}
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
new file mode 100644
index 00000000..7a629319
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/interceptor/NacosConfigConstructorInterceptor.java
@@ -0,0 +1,58 @@
+/*
+ * 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.nacos.interceptor;
+
+import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+import cn.hippo4j.agent.plugin.nacos.NacosDynamicThreadPoolChangeHandler;
+import cn.hippo4j.agent.plugin.nacos.listeners.NacosConfigPropertiesLoaderCompletedListener;
+import cn.hippo4j.agent.plugin.spring.common.support.SpringPropertiesLoader;
+import cn.hippo4j.common.extension.design.AbstractSubjectCenter;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Nacos config constructor interceptor
+ */
+public class NacosConfigConstructorInterceptor implements InstanceConstructorInterceptor {
+
+ private static final AtomicBoolean isExecuted = new AtomicBoolean(false);
+
+ @Override
+ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable {
+ // This logic will only be executed once
+ if (isExecuted.compareAndSet(false, true)) {
+
+ // 判断 SpringPropertiesLoader 是否初始化
+ AtomicBoolean active = SpringPropertiesLoader.getActive();
+
+ // For Nacos-Cloud, the SpringPropertiesLoader environment initialization is triggered first, and then the logic to register listeners is triggered
+ // For Nacos-Boot, the listener is registered first, and the SpringPropertiesLoader environment is initialized
+ if (Boolean.TRUE.equals(active.get())) {
+ new NacosDynamicThreadPoolChangeHandler().registerListener();
+ return;
+ }
+
+ // 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,
+ // so the configuration cannot be read
+ // After listening to the AGENT_SPRING_PROPERTIES_LOADER_COMPLETED event, register the listener for Apollo
+ AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.AGENT_SPRING_PROPERTIES_LOADER_COMPLETED, new NacosConfigPropertiesLoaderCompletedListener());
+ }
+ }
+}
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/listeners/NacosConfigPropertiesLoaderCompletedListener.java b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/listeners/NacosConfigPropertiesLoaderCompletedListener.java
new file mode 100644
index 00000000..fa7a795b
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/java/cn/hippo4j/agent/plugin/nacos/listeners/NacosConfigPropertiesLoaderCompletedListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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.nacos.listeners;
+
+import cn.hippo4j.agent.plugin.nacos.NacosDynamicThreadPoolChangeHandler;
+import cn.hippo4j.common.extension.design.Observer;
+import cn.hippo4j.common.extension.design.ObserverMessage;
+import cn.hippo4j.threadpool.dynamic.api.ThreadPoolDynamicRefresh;
+
+/**
+ * Nacos Config Properties Loader Completed Listener
+ */
+public class NacosConfigPropertiesLoaderCompletedListener implements Observer {
+
+ @Override
+ public void accept(ObserverMessage observerMessage) {
+ ThreadPoolDynamicRefresh dynamicRefresh = new NacosDynamicThreadPoolChangeHandler();
+ dynamicRefresh.registerListener();
+ }
+}
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/resources/META-INF/services/cn.hippo4j.agent.core.boot.BootService
new file mode 100644
index 00000000..5337b3b0
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-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.nacos.boot.NacosPluginBootService
\ No newline at end of file
diff --git a/agent/hippo4j-agent-plugin/nacos-plugin/src/main/resources/hippo4j-plugin.def b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/resources/hippo4j-plugin.def
new file mode 100644
index 00000000..fb175826
--- /dev/null
+++ b/agent/hippo4j-agent-plugin/nacos-plugin/src/main/resources/hippo4j-plugin.def
@@ -0,0 +1,18 @@
+# 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.
+
+nacos-plugin=cn.hippo4j.agent.plugin.nacos.define.NacosInstrumentation
+nacos-cloud-adapter-plugin=cn.hippo4j.agent.plugin.nacos.define.NacosCloudAdapterInstrumentation
\ No newline at end of file
diff --git a/agent/hippo4j-agent-plugin/pom.xml b/agent/hippo4j-agent-plugin/pom.xml
index 4a3f7954..0217b17b 100644
--- a/agent/hippo4j-agent-plugin/pom.xml
+++ b/agent/hippo4j-agent-plugin/pom.xml
@@ -16,6 +16,7 @@
threadpool-plugin
adapter-plugins
apollo-plugin
+ nacos-plugin
diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/EventPublishingRunListenerInstrumentation.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/ApplicationContextInstrumentation.java
similarity index 51%
rename from agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/EventPublishingRunListenerInstrumentation.java
rename to agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/ApplicationContextInstrumentation.java
index 06c93998..315f3a96 100644
--- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/EventPublishingRunListenerInstrumentation.java
+++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/define/ApplicationContextInstrumentation.java
@@ -28,18 +28,17 @@ 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;
+import static net.bytebuddy.matcher.ElementMatchers.named;
/**
- * Event publishing run listener instrumentation
+ * Application Context Refresh instrumentation
*/
-public class EventPublishingRunListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+public class ApplicationContextInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
- private static final String ENHANCE_CLASS = "org.springframework.boot.context.event.EventPublishingRunListener";
+ private static final String ENHANCE_CLASS = "org.springframework.context.support.AbstractApplicationContext";
- private static final String EVENT_PUBLISHING_FINISHED_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.boot.v1.interceptor.EventPublishingFinishedInterceptor";
- private static final String EVENT_PUBLISHING_ENVIRONMENT_PREPARED_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.common.interceptor.EventPublishingRunListenerEnvironmentPreparedInterceptor";
+ private static final String APPLICATION_CONTEXT_REFRESH_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.boot.v1.interceptor.ApplicationContextInterceptor";
@Override
protected ClassMatch enhanceClass() {
@@ -53,47 +52,27 @@ public class EventPublishingRunListenerInstrumentation extends ClassInstanceMeth
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
- return new InstanceMethodsInterceptPoint[]{
- new InstanceMethodsInterceptPoint() {
-
- @Override
- public ElementMatcher getMethodsMatcher() {
- return named("finished");
- }
-
- @Override
- public String getMethodsInterceptor() {
- return EVENT_PUBLISHING_FINISHED_INTERCEPTOR;
- }
-
- @Override
- public boolean isOverrideArgs() {
- return false;
- }
- },
- new InstanceMethodsInterceptPoint() {
-
- @Override
- public ElementMatcher getMethodsMatcher() {
- return named("environmentPrepared");
- }
-
- @Override
- public String getMethodsInterceptor() {
- return EVENT_PUBLISHING_ENVIRONMENT_PREPARED_INTERCEPTOR;
- }
-
- @Override
- public boolean isOverrideArgs() {
- return false;
- }
- }
- };
+ return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() {
+
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("refresh");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return APPLICATION_CONTEXT_REFRESH_INTERCEPTOR;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }};
}
@Override
protected List witnessMethods() {
- return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener",
- named("finished")));
+ return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", named("finished")));
}
}
diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/ApplicationContextInterceptor.java
similarity index 64%
rename from agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java
rename to agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/ApplicationContextInterceptor.java
index dcee8726..8297bfb9 100644
--- a/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/EventPublishingFinishedInterceptor.java
+++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/java/cn/hippo4j/agent/plugin/spring/boot/v1/interceptor/ApplicationContextInterceptor.java
@@ -17,29 +17,25 @@
package cn.hippo4j.agent.plugin.spring.boot.v1.interceptor;
-import cn.hippo4j.agent.adapter.dubbo.DubboThreadPoolAdapter;
-import cn.hippo4j.common.logging.api.ILog;
-import cn.hippo4j.common.logging.api.LogManager;
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.boot.v1.DynamicThreadPoolChangeHandlerSpring1x;
+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.threadpool.dynamic.api.ThreadPoolDynamicRefresh;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import cn.hippo4j.common.extension.design.AbstractSubjectCenter;
+import cn.hippo4j.core.config.ApplicationContextHolder;
import org.springframework.context.ConfigurableApplicationContext;
import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
- * Event publishing finished interceptor
+ * Application Context Refresh interceptor
*/
-public class EventPublishingFinishedInterceptor implements InstanceMethodsAroundInterceptor {
+public class ApplicationContextInterceptor implements InstanceMethodsAroundInterceptor {
- private static final ILog FILE_LOGGER = LogManager.getLogger(EventPublishingFinishedInterceptor.class);
- private static final Logger LOGGER = LoggerFactory.getLogger(EventPublishingFinishedInterceptor.class);
+ private static final AtomicBoolean isExecuted = new AtomicBoolean(false);
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
@@ -48,16 +44,22 @@ public class EventPublishingFinishedInterceptor implements InstanceMethodsAround
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes, Object ret) throws Throwable {
- ConfigurableApplicationContext context = (ConfigurableApplicationContext) allArguments[0];
+ // 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;
if (context.getParent() != null) {
// After the child container is started, the thread pool registration will be carried out
SpringThreadPoolRegisterSupport.registerThreadPoolInstances(context);
return ret;
}
- SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());
- ThreadPoolDynamicRefresh dynamicRefreshSpring1x = new DynamicThreadPoolChangeHandlerSpring1x(context);
- dynamicRefreshSpring1x.registerListener();
- DubboThreadPoolAdapter.registerExecutors();
+ // This logic will only be executed once
+ if (isExecuted.compareAndSet(false, true)) {
+ ApplicationContextHolder contextHolder = new ApplicationContextHolder();
+ contextHolder.setApplicationContext(context);
+ SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());
+ 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/hippo4j-plugin.def b/agent/hippo4j-agent-plugin/spring-plugins/spring-boot-1x-plugin/src/main/resources/hippo4j-plugin.def
index 8bb37e3a..403de5ce 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.EventPublishingRunListenerInstrumentation
\ No newline at end of file
+spring-boot-1.x=cn.hippo4j.agent.plugin.spring.boot.v1.define.ApplicationContextInstrumentation
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/EventPublishingStartedInterceptor.java
index 45423564..74faef32 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/EventPublishingStartedInterceptor.java
@@ -17,29 +17,28 @@
package cn.hippo4j.agent.plugin.spring.boot.v2.interceptor;
-import cn.hippo4j.agent.plugin.spring.boot.v2.NacosDynamicThreadPoolChangeHandlerSpring2x;
-import cn.hippo4j.common.logging.api.ILog;
-import cn.hippo4j.common.logging.api.LogManager;
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.boot.v2.DynamicThreadPoolChangeHandlerSpring2x;
+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.threadpool.dynamic.api.ThreadPoolDynamicRefresh;
-import cn.hippo4j.threadpool.dynamic.mode.config.refresher.event.DynamicThreadPoolRefreshListener;
-import lombok.extern.slf4j.Slf4j;
+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
*/
-@Slf4j
public class EventPublishingStartedInterceptor implements InstanceMethodsAroundInterceptor {
+ private static final AtomicBoolean isExecuted = new AtomicBoolean(false);
+
private static final ILog LOGGER = LogManager.getLogger(EventPublishingStartedInterceptor.class);
@Override
@@ -55,13 +54,15 @@ public class EventPublishingStartedInterceptor implements InstanceMethodsAroundI
SpringThreadPoolRegisterSupport.registerThreadPoolInstances(context);
return ret;
}
- SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());
- // ThreadPoolDynamicRefresh dynamicRefresh = new DynamicThreadPoolChangeHandlerSpring2x();
- // TODO Nacos配置
- ThreadPoolDynamicRefresh dynamicRefresh = new NacosDynamicThreadPoolChangeHandlerSpring2x();
- dynamicRefresh.registerListener();
- AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH,
- new DynamicThreadPoolRefreshListener());
+ // 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());
+ // register Dynamic ThreadPool Refresh Listener
+ AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener());
+ }
return ret;
}
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 c472c7b3..853e0706 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
@@ -55,6 +55,11 @@
${project.version}
provided
+
+ cn.hippo4j
+ hippo4j-threadpool-infra-common
+ ${project.version}
+
cn.hippo4j
hippo4j-threadpool-monitor-elasticsearch
diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringEnvironmentSupport.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringEnvironmentSupport.java
index 4733acdc..d4b7e619 100644
--- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringEnvironmentSupport.java
+++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringEnvironmentSupport.java
@@ -32,6 +32,6 @@ public class SpringEnvironmentSupport {
Map map = new HashMap<>();
map.put("spring.dynamic.thread-pool.enable", false); // Switch off in non-Agent mode
MapPropertySource propertySource = new MapPropertySource("Hippo4j-Agent-Properties", map);
- environment.getPropertySources().addFirst(propertySource);
+ environment.getPropertySources().addLast(propertySource);
}
}
diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringPropertiesLoader.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringPropertiesLoader.java
index d9fbfac7..a73c800e 100644
--- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringPropertiesLoader.java
+++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/SpringPropertiesLoader.java
@@ -19,19 +19,24 @@ package cn.hippo4j.agent.plugin.spring.common.support;
import cn.hippo4j.agent.core.boot.SpringBootConfigInitializer;
import cn.hippo4j.agent.plugin.spring.common.toolkit.SpringPropertyBinder;
+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.toolkit.inet.InetUtilsProperties;
import cn.hippo4j.threadpool.dynamic.mode.config.properties.BootstrapConfigProperties;
+import lombok.Getter;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import static cn.hippo4j.threadpool.dynamic.mode.config.properties.BootstrapConfigProperties.PREFIX;
/**
@@ -41,6 +46,13 @@ public class SpringPropertiesLoader {
private static final ILog LOGGER = LogManager.getLogger(SpringPropertiesLoader.class);
+ /**
+ * A flag used to indicate whether loadSpringProperties() method has been called,
+ * Used to determine whether the SpringPropertiesLoader has been initialized
+ */
+ @Getter
+ private static final AtomicBoolean active = new AtomicBoolean(Boolean.FALSE);
+
public static BootstrapConfigProperties BOOTSTRAP_CONFIG_PROPERTIES = new BootstrapConfigProperties();
public static InetUtilsProperties INET_UTILS_PROPERTIES = new InetUtilsProperties();
@@ -54,13 +66,11 @@ public class SpringPropertiesLoader {
}
// Sort to ensure that the configuration in the configuration center is after the array
// To get the latest configuration information
- propertySourceList.sort((o1, o2) -> {
- boolean o1Contains = o1.getName().toLowerCase().contains("apollo") || o1.getName().toLowerCase().contains("nacos");
- boolean o2Contains = (o2.getName().toLowerCase().contains("apollo") || o2.getName().toLowerCase().contains("nacos"));
- return Boolean.compare(o1Contains, o2Contains);
- });
+ propertySourceList.sort(Comparator.comparing(
+ // Make sure that Nacos boot's propertySource is placed first in the propertySourceList
+ item -> !item.getClass().getName().equals("com.alibaba.nacos.spring.core.env.NacosPropertySource")));
- for (int i = 0; i <= propertySourceList.size() - 1; i++) {
+ for (int i = propertySourceList.size() - 1; i >= 0; i--) {
PropertySource> propertySource = propertySourceList.get(i);
if (!(propertySource instanceof EnumerablePropertySource)) {
LOGGER.warn("Skip propertySource[{}] because {} not enumerable.", propertySource.getName(), propertySource.getClass());
@@ -87,6 +97,11 @@ public class SpringPropertiesLoader {
// initialize BootstrapConfigProperties
BOOTSTRAP_CONFIG_PROPERTIES = SpringPropertyBinder.bindProperties(environment, PREFIX, BootstrapConfigProperties.class);
INET_UTILS_PROPERTIES = SpringPropertyBinder.bindProperties(environment, InetUtilsProperties.PREFIX, InetUtilsProperties.class);
+ // Send AGENT_SPRING_PROPERTIES_LOADER_COMPLETED notification event Before active is false
+ if (AbstractSubjectCenter.get(AbstractSubjectCenter.SubjectType.AGENT_SPRING_PROPERTIES_LOADER_COMPLETED) != null && Boolean.FALSE.equals(active.get())) {
+ AbstractSubjectCenter.notify(AbstractSubjectCenter.SubjectType.AGENT_SPRING_PROPERTIES_LOADER_COMPLETED, () -> "");
+ }
+ active.set(Boolean.TRUE);
// Enable the thread pool check alert handler
ThreadPoolCheckAlarmSupport.enableThreadPoolCheckAlarmHandler();
// Enable thread pool monitor handler
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 a5d0334a..4cbd54e3 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
@@ -17,11 +17,9 @@
package cn.hippo4j.agent.plugin.spring.common.support;
-import cn.hippo4j.adapter.web.jetty.DefaultJettyWebThreadPoolHandler;
import cn.hippo4j.agent.plugin.spring.common.alarm.AgentModeNotifyConfigBuilder;
import cn.hippo4j.agent.plugin.spring.common.conf.SpringBootConfig;
import cn.hippo4j.agent.plugin.spring.common.toolkit.SpringPropertyBinder;
-import cn.hippo4j.common.api.ThreadPoolConfigChange;
import cn.hippo4j.common.propertie.EnvironmentProperties;
import cn.hippo4j.core.config.ApplicationContextHolder;
import cn.hippo4j.core.toolkit.IdentifyUtil;
@@ -36,7 +34,6 @@ import cn.hippo4j.threadpool.message.core.service.AlarmControlHandler;
import cn.hippo4j.threadpool.message.core.service.DefaultThreadPoolConfigChangeHandler;
import cn.hippo4j.threadpool.message.core.service.SendMessageHandler;
import cn.hippo4j.threadpool.message.core.service.ThreadPoolBaseSendMessageService;
-import cn.hippo4j.threadpool.message.core.service.ThreadPoolSendMessageService;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -65,6 +62,8 @@ public class ThreadPoolCheckAlarmSupport {
@Getter
private static AgentModeNotifyConfigBuilder agentNotifyConfigBuilder;
+ private static DefaultThreadPoolCheckAlarmHandler checkAlarmHandler;
+
/**
* Enables the thread pool check alarm handler if the corresponding configuration property is set to {@code true}.
*
@@ -92,11 +91,8 @@ public class ThreadPoolCheckAlarmSupport {
// Initialize the alarm platform information
initializeSendMessageHandlers(threadPoolBaseSendMessageService, alarmControlHandler);
- // Initialize the thread pool check alarm handler with necessary services
- DefaultThreadPoolCheckAlarmHandler checkAlarmHandler = new DefaultThreadPoolCheckAlarmHandler(threadPoolBaseSendMessageService);
-
- // Run the check alarm handler to start monitoring the thread pool
- checkAlarmHandler.scheduleExecute();
+ // Execute scheduled task to check an alarm
+ scheduleExecute(threadPoolBaseSendMessageService);
}
}
@@ -134,7 +130,7 @@ public class ThreadPoolCheckAlarmSupport {
* It also constructs and registers notification configurations using the {@link AgentModeNotifyConfigBuilder}.
*
* @param threadPoolBaseSendMessageService The {@link ThreadPoolBaseSendMessageService} in which message handlers and notification configurations will be registered.
- * @param alarmControlHandler The {@link AlarmControlHandler} used to handle alarms and notifications.
+ * @param alarmControlHandler The {@link AlarmControlHandler} used to handle alarms and notifications.
*/
private static void initializeSendMessageHandlers(ThreadPoolBaseSendMessageService threadPoolBaseSendMessageService, AlarmControlHandler alarmControlHandler) {
// Initialize message handlers
@@ -153,4 +149,17 @@ public class ThreadPoolCheckAlarmSupport {
Map> notifyConfigs = agentNotifyConfigBuilder.buildNotify();
threadPoolBaseSendMessageService.getNotifyConfigs().putAll(notifyConfigs);
}
+
+ // 启动或重新启动检查任务
+ public static void scheduleExecute(ThreadPoolBaseSendMessageService threadPoolBaseSendMessageService) {
+ // If a task is already running, cancel it first
+ if (checkAlarmHandler != null) {
+ // Shut down the thread pool and prepare to regenerate the listener thread pool
+ checkAlarmHandler.destroyScheduleExecute();
+ }
+ // Initialize the thread pool check alarm handler with necessary services
+ checkAlarmHandler = new DefaultThreadPoolCheckAlarmHandler(threadPoolBaseSendMessageService);
+ // Run the check alarm handler to start monitoring the thread pool
+ checkAlarmHandler.scheduleExecute();
+ }
}
diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolMonitorSupport.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolMonitorSupport.java
index 3af1e1e6..d44dbf3d 100644
--- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolMonitorSupport.java
+++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/support/ThreadPoolMonitorSupport.java
@@ -19,7 +19,6 @@ package cn.hippo4j.agent.plugin.spring.common.support;
import cn.hippo4j.agent.plugin.spring.common.monitor.MonitorHandlersConfigurator;
import cn.hippo4j.agent.plugin.spring.common.monitor.MonitorMetricEndpoint;
-import cn.hippo4j.common.executor.ThreadFactoryBuilder;
import cn.hippo4j.common.executor.ThreadPoolExecutorRegistry;
import cn.hippo4j.common.extension.spi.ServiceLoaderRegistry;
import cn.hippo4j.common.monitor.MonitorCollectTypeEnum;
@@ -27,6 +26,7 @@ import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.threadpool.dynamic.mode.config.properties.BootstrapConfigProperties;
import cn.hippo4j.threadpool.dynamic.mode.config.properties.MonitorProperties;
import cn.hippo4j.threadpool.monitor.api.ThreadPoolMonitor;
+import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -36,10 +36,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
-import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import static cn.hippo4j.agent.plugin.spring.common.support.SpringPropertiesLoader.BOOTSTRAP_CONFIG_PROPERTIES;
@@ -52,7 +52,16 @@ public class ThreadPoolMonitorSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolMonitorSupport.class);
- private static List threadPoolMonitors;
+ /**
+ * A flag used to indicate whether enableThreadPoolMonitorHandler() method has been called,
+ * Used to determine whether the ThreadPoolMonitorHandler has been enable
+ */
+ @Getter
+ private static final AtomicBoolean active = new AtomicBoolean(Boolean.FALSE);
+
+ private static final ScheduledExecutorService collectScheduledExecutor = new ScheduledThreadPoolExecutor(1, r -> new Thread(r, "client.agent.scheduled.collect.data"));
+
+ private static final List threadPoolMonitors = new ArrayList<>();
static {
// Register the ThreadPoolMonitor service with the ServiceLoaderRegistry
@@ -78,22 +87,19 @@ public class ThreadPoolMonitorSupport {
public static void enableThreadPoolMonitorHandler(Environment environment) {
BootstrapConfigProperties properties = BOOTSTRAP_CONFIG_PROPERTIES;
MonitorProperties monitor = properties.getMonitor();
- if (Objects.isNull(monitor)
- || !monitor.getEnable()
- || StringUtil.isBlank(monitor.getThreadPoolTypes())
- || StringUtil.isBlank(monitor.getCollectTypes())) {
+ if (Objects.isNull(monitor) || !monitor.getEnable() || StringUtil.isBlank(monitor.getThreadPoolTypes()) || StringUtil.isBlank(monitor.getCollectTypes())) {
return;
}
LOGGER.info("[Hippo4j-Agent] Start monitoring the running status of dynamic thread pools.");
- threadPoolMonitors = new ArrayList<>();
- ScheduledExecutorService collectScheduledExecutor = new ScheduledThreadPoolExecutor(
- 1,
- r -> new Thread(r, "client.agent.scheduled.collect.data"));
// Initialize monitoring components for the dynamic thread pools
MonitorHandlersConfigurator.initializeMonitorHandlers(monitor, (ConfigurableEnvironment) environment, threadPoolMonitors);
+ // Determine whether the task is successfully enabled
+ // return directly if it has been enabled, and do not start the thread pool repeatedly
+ if (Boolean.TRUE.equals(active.get())) return;
+
// Expose metric endpoints based on the configured collect types
List collectTypes = Arrays.asList(monitor.getCollectTypes().split(","));
if (collectTypes.contains(MonitorCollectTypeEnum.MICROMETER.getValue())) {
@@ -101,12 +107,9 @@ public class ThreadPoolMonitorSupport {
}
// Schedule periodic collection of metrics from the thread pools
- collectScheduledExecutor.scheduleWithFixedDelay(
- scheduleRunnable(),
- monitor.getInitialDelay(),
- monitor.getCollectInterval(),
- TimeUnit.MILLISECONDS);
+ collectScheduledExecutor.scheduleWithFixedDelay(scheduleRunnable(), monitor.getInitialDelay(), monitor.getCollectInterval(), TimeUnit.MILLISECONDS);
+ active.set(true);
if (ThreadPoolExecutorRegistry.getThreadPoolExecutorSize() > 0) {
LOGGER.info("[Hippo4j-Agent] Dynamic thread pool: [{}]. The dynamic thread pool starts data collection and reporting.", ThreadPoolExecutorRegistry.getThreadPoolExecutorSize());
}
diff --git a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/toolkit/SpringPropertyBinder.java b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/toolkit/SpringPropertyBinder.java
index 4491eb70..22a6bc62 100644
--- a/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/toolkit/SpringPropertyBinder.java
+++ b/agent/hippo4j-agent-plugin/spring-plugins/spring-plugin-common/src/main/java/cn/hippo4j/agent/plugin/spring/common/toolkit/SpringPropertyBinder.java
@@ -72,6 +72,39 @@ public class SpringPropertyBinder {
}
}
+ /**
+ * Binds properties from a map to an instance of the specified configuration class.
+ *
+ * @param configInfo a map containing property paths and their values.
+ * @param prefix the prefix to filter properties for binding (e.g., "spring.dynamic.thread-pool").
+ * @param clazz the class type of the configuration object to bind properties to.
+ * @param the type of the configuration class.
+ * @return an instance of the configuration class with properties bound from the configInfo map.
+ */
+ public static T bindProperties(Map configInfo, String prefix, Class clazz) {
+ try {
+ // Create an instance of the target class
+ T instance = clazz.getDeclaredConstructor().newInstance();
+ BeanWrapper beanWrapper = new BeanWrapperImpl(instance);
+
+ // Register custom editor for specific type conversions (if needed)
+ beanWrapper.registerCustomEditor(ConfigFileTypeEnum.class, new ConfigFileTypeEnumEditor());
+
+ // Iterate over all property keys that match the given prefix in the configInfo map
+ for (Map.Entry entry : configInfo.entrySet()) {
+ String key = entry.getKey().toString();
+ if (key.startsWith(prefix)) {
+ String propertyName = key.substring(prefix.length() + 1); // Remove prefix from the property key
+ String[] tokens = propertyName.split("\\."); // Split the property name by dot for nested properties
+ setPropertyValue(tokens, beanWrapper, entry.getValue().toString()); // Set the property value recursively
+ }
+ }
+ return instance;
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to bind properties to " + clazz.getName(), e);
+ }
+ }
+
/**
* Recursively sets property values on the target object, handling nested properties and collections.
*
diff --git a/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/resources/bootstrap.properties b/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/resources/bootstrap.properties
new file mode 100644
index 00000000..7a691206
--- /dev/null
+++ b/examples/threadpool-example/agent/config-apollo-spring-boot-1x/src/main/resources/bootstrap.properties
@@ -0,0 +1,53 @@
+server.port=8092
+server.servlet.context-path=/example
+
+app.id=dynamic-threadpool-example
+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
+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
+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.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.core.config.ThreadPoolConfiguration#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
diff --git a/examples/threadpool-example/agent/config-apollo/src/main/resources/bootstrap.properties b/examples/threadpool-example/agent/config-apollo/src/main/resources/bootstrap.properties
index d467930f..7a691206 100644
--- a/examples/threadpool-example/agent/config-apollo/src/main/resources/bootstrap.properties
+++ b/examples/threadpool-example/agent/config-apollo/src/main/resources/bootstrap.properties
@@ -1,11 +1,13 @@
server.port=8092
server.servlet.context-path=/example
+
app.id=dynamic-threadpool-example
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
@@ -14,26 +16,29 @@ spring.application.name=hippo4j-config-apollo-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=3
-#spring.dynamic.thread-pool.monitor.enable=true
-#spring.dynamic.thread-pool.monitor.collect-types=micrometer
-#spring.dynamic.thread-pool.monitor.thread-pool-types=dynamic,web
-#spring.dynamic.thread-pool.monitor.initial-delay=10000
-#spring.dynamic.thread-pool.monitor.collect-interval=5000
-#spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
-#spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff
-#spring.dynamic.thread-pool.notify-platforms[1].platform=DING
-#spring.dynamic.thread-pool.notify-platforms[1].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
-#spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
-#spring.dynamic.thread-pool.notify-platforms[2].token=2cbf2808-3839-4c26-a04d-fd201dd51f9e
+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.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.ThreadPoolConfiguration#RUN_MESSAGE_SEND_TASK_EXECUTOR
+spring.dynamic.thread-pool.executors[0].thread-pool-id = cn.hippo4j.example.agent.core.config.ThreadPoolConfiguration#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
diff --git a/examples/threadpool-example/agent/config-nacos-spring-boot-1x/pom.xml b/examples/threadpool-example/agent/config-nacos-spring-boot-1x/pom.xml
new file mode 100644
index 00000000..011342c8
--- /dev/null
+++ b/examples/threadpool-example/agent/config-nacos-spring-boot-1x/pom.xml
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+
+ cn.hippo4j
+ hippo4j-threadpool-agent-example
+ ${revision}
+
+
+ hippo4j-threadpool-agent-config-nacos-spring-boot-1x
+
+
+ true
+ 1.5.22.RELEASE
+
+
+
+
+ cn.hippo4j
+ hippo4j-agent-example-core
+ ${revision}
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+ 1.5.1.RELEASE
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-context
+ 1.3.0.RELEASE
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+
+
+ ${project.artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/threadpool-example/agent/config-nacos-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/nacos/v1/AgentConfigNacosSpringBoot1xExampleApplication.java b/examples/threadpool-example/agent/config-nacos-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/nacos/v1/AgentConfigNacosSpringBoot1xExampleApplication.java
new file mode 100644
index 00000000..eceee1b4
--- /dev/null
+++ b/examples/threadpool-example/agent/config-nacos-spring-boot-1x/src/main/java/cn/hippo4j/example/agent/config/nacos/v1/AgentConfigNacosSpringBoot1xExampleApplication.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.nacos.v1;
+
+import com.alibaba.nacos.api.exception.NacosException;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Agent config Nacos example application.
+ */
+@SpringBootApplication(scanBasePackages = "cn.hippo4j.example.agent.core")
+public class AgentConfigNacosSpringBoot1xExampleApplication {
+
+ public static void main(String[] args) throws NacosException {
+ SpringApplication.run(AgentConfigNacosSpringBoot1xExampleApplication.class, args);
+ }
+}
diff --git a/examples/threadpool-example/agent/config-nacos-spring-boot-1x/src/main/resources/bootstrap.properties b/examples/threadpool-example/agent/config-nacos-spring-boot-1x/src/main/resources/bootstrap.properties
new file mode 100644
index 00000000..4291d582
--- /dev/null
+++ b/examples/threadpool-example/agent/config-nacos-spring-boot-1x/src/main/resources/bootstrap.properties
@@ -0,0 +1,60 @@
+server.port=8092
+server.servlet.context-path=/example
+spring.profiles.active=dev
+spring.application.name=hippo4j-config-nacos-spring-boot-starter-example
+
+# The following parameters are used for testing
+spring.cloud.nacos.config.server-addr=127.0.0.1:8848
+spring.cloud.nacos.config.name=dynamic-threadpool-example-config
+spring.cloud.nacos.config.file-extension=properties
+spring.cloud.nacos.config.refresh.enabled=true
+
+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.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.server-addr=127.0.0.1:8848
+spring.dynamic.thread-pool.nacos.data-id=dynamic-threadpool-example-config
+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.core.config.ThreadPoolConfiguration#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
diff --git a/examples/threadpool-example/agent/config-nacos/pom.xml b/examples/threadpool-example/agent/config-nacos/pom.xml
index 8134d488..068ff153 100644
--- a/examples/threadpool-example/agent/config-nacos/pom.xml
+++ b/examples/threadpool-example/agent/config-nacos/pom.xml
@@ -29,10 +29,15 @@
org.springframework.boot
spring-boot-starter-web
-
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+ 2.2.5.RELEASE
org.springframework.cloud
diff --git a/examples/threadpool-example/agent/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/AgentConfigNacosExampleApplication.java b/examples/threadpool-example/agent/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/AgentConfigNacosExampleApplication.java
index e5010fbd..1b315207 100644
--- a/examples/threadpool-example/agent/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/AgentConfigNacosExampleApplication.java
+++ b/examples/threadpool-example/agent/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/AgentConfigNacosExampleApplication.java
@@ -17,8 +17,6 @@
package cn.hippo4j.example.agent.config.nacos;
-import com.alibaba.nacos.api.exception.NacosException;
-import com.alibaba.nacos.spring.context.annotation.config.EnableNacosConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -26,10 +24,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* Agent config Nacos example application.
*/
@SpringBootApplication(scanBasePackages = "cn.hippo4j.example.agent.core")
-@EnableNacosConfig
public class AgentConfigNacosExampleApplication {
- public static void main(String[] args) throws NacosException {
+ public static void main(String[] args) {
SpringApplication.run(AgentConfigNacosExampleApplication.class, args);
}
}
diff --git a/examples/threadpool-example/agent/config-nacos/src/main/resources/bootstrap.properties b/examples/threadpool-example/agent/config-nacos/src/main/resources/bootstrap.properties
index f145868b..c9b6820e 100644
--- a/examples/threadpool-example/agent/config-nacos/src/main/resources/bootstrap.properties
+++ b/examples/threadpool-example/agent/config-nacos/src/main/resources/bootstrap.properties
@@ -4,8 +4,12 @@ server.servlet.context-path=/example
nacos.config.auto-refresh=true
nacos.config.bootstrap.enable=true
# The following parameters are used for testing
-nacos.config.server-addr=127.0.0.1:8848
-nacos.config.data-id=dynamic-threadpool-example-config
+
+spring.cloud.nacos.config.server-addr=127.0.0.1:8848
+spring.cloud.nacos.config.extension-configs[0].data-id=dynamic-threadpool-example-config
+spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
+spring.cloud.nacos.config.extension-configs[0].refresh=true
+
spring.profiles.active=dev
spring.application.name=hippo4j-config-nacos-spring-boot-starter-example
management.metrics.export.prometheus.enabled=true
@@ -13,18 +17,21 @@ 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=3
+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.initial-delay=10000
-#spring.dynamic.thread-pool.monitor.collect-interval=5000
-#spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
-#spring.dynamic.thread-pool.notify-platforms[0].token=ac0426a5-c712-474c-9bff-72b8b8f5caff
-#spring.dynamic.thread-pool.notify-platforms[1].platform=DING
-#spring.dynamic.thread-pool.notify-platforms[1].token=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
-#spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
-#spring.dynamic.thread-pool.notify-platforms[2].token=2cbf2808-3839-4c26-a04d-fd201dd51f9e
+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.server-addr=127.0.0.1:8848
spring.dynamic.thread-pool.nacos.data-id=dynamic-threadpool-example-config
spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP
@@ -34,7 +41,7 @@ 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.ThreadPoolConfiguration#RUN_MESSAGE_SEND_TASK_EXECUTOR
+spring.dynamic.thread-pool.executors[0].thread-pool-id = cn.hippo4j.example.agent.core.config.ThreadPoolConfiguration#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
diff --git a/examples/threadpool-example/agent/pom.xml b/examples/threadpool-example/agent/pom.xml
index d215c979..fcbe2ce2 100644
--- a/examples/threadpool-example/agent/pom.xml
+++ b/examples/threadpool-example/agent/pom.xml
@@ -20,5 +20,7 @@
config-apollo
config-nacos
agent-example-core
+ config-nacos-spring-boot-1x
+ config-apollo-spring-boot-1x
\ No newline at end of file
diff --git a/examples/threadpool-example/config/config-nacos/src/main/java/cn/hippo4j/example/config/nacos/ConfigNacosExampleApplication.java b/examples/threadpool-example/config/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/ConfigNacosExampleApplication.java
similarity index 96%
rename from examples/threadpool-example/config/config-nacos/src/main/java/cn/hippo4j/example/config/nacos/ConfigNacosExampleApplication.java
rename to examples/threadpool-example/config/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/ConfigNacosExampleApplication.java
index fda32d1e..db2f8ea9 100644
--- a/examples/threadpool-example/config/config-nacos/src/main/java/cn/hippo4j/example/config/nacos/ConfigNacosExampleApplication.java
+++ b/examples/threadpool-example/config/config-nacos/src/main/java/cn/hippo4j/example/agent/config/nacos/ConfigNacosExampleApplication.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package cn.hippo4j.example.config.nacos;
+package cn.hippo4j.example.agent.config.nacos;
import cn.hippo4j.core.enable.EnableDynamicThreadPool;
import org.springframework.boot.SpringApplication;
diff --git a/kernel/alarm/src/main/java/cn/hippo4j/threadpool/alarm/handler/DefaultThreadPoolCheckAlarmHandler.java b/kernel/alarm/src/main/java/cn/hippo4j/threadpool/alarm/handler/DefaultThreadPoolCheckAlarmHandler.java
index f4b7710f..0f6cba86 100644
--- a/kernel/alarm/src/main/java/cn/hippo4j/threadpool/alarm/handler/DefaultThreadPoolCheckAlarmHandler.java
+++ b/kernel/alarm/src/main/java/cn/hippo4j/threadpool/alarm/handler/DefaultThreadPoolCheckAlarmHandler.java
@@ -235,4 +235,17 @@ public class DefaultThreadPoolCheckAlarmHandler implements Runnable, ThreadPoolC
.rejectCountNum(rejectCount)
.build();
}
+
+ /**
+ * Terminates the scheduled tasks and asynchronous alarm notifications by
+ * forcefully shutting down the respective thread pools.
+ *
+ * @see alarmNotifyExecutor
+ * @see asyncAlarmNotifyExecutor
+ */
+ public void destroyScheduleExecute() {
+ alarmNotifyExecutor.shutdownNow();
+ asyncAlarmNotifyExecutor.shutdownNow();
+ }
+
}