-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature : Agent mode supports dynamic thread pool changes, alarm and …
…monitoring functions without modifying code, and adapts to Nacos and Apollo Configuration Centers (#1572) * fix:Fix send threadPool change notification message log * feat:Agent Nacos dynamic refresh Initialize * feat:Agent dynamic alarm Initialize * feat:Agent dynamic monitor Initialize * refactor:Agent Listener logic, add configuration refreshes platform push, and carries the unique application ID * feat:Apollo Configuration Center Plugin Logic Adaptation * feat:Completed the implementation of Nacos Configuration Center plugin and Nacos,Apollo plugins adapted to Spring 1.x , 2.x environment * fix: Fixed jar package mounting and startup problem in Agent mode
- Loading branch information
Showing
69 changed files
with
3,130 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
...n/java/cn/hippo4j/agent/plugin/apollo/interceptor/ApolloConfigConstructorInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* 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.apollo.interceptor; | ||
|
||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.EnhancedInstance; | ||
import cn.hippo4j.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; | ||
import cn.hippo4j.agent.plugin.apollo.listeners.ApolloConfigPropertiesLoaderCompletedListener; | ||
import cn.hippo4j.common.extension.design.AbstractSubjectCenter; | ||
|
||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
/** | ||
* Default config constructor interceptor | ||
*/ | ||
public class ApolloConfigConstructorInterceptor 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)) { | ||
// The Apollo 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 ApolloConfigPropertiesLoaderCompletedListener()); | ||
} | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
.../hippo4j/agent/plugin/apollo/listeners/ApolloConfigPropertiesLoaderCompletedListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.apollo.listeners; | ||
|
||
import cn.hippo4j.agent.plugin.apollo.ApolloDynamicThreadPoolChangeHandler; | ||
import cn.hippo4j.common.extension.design.Observer; | ||
import cn.hippo4j.common.extension.design.ObserverMessage; | ||
import cn.hippo4j.threadpool.dynamic.api.ThreadPoolDynamicRefresh; | ||
|
||
/** | ||
* Apollo Config Properties Loader Completed Listener | ||
*/ | ||
public class ApolloConfigPropertiesLoaderCompletedListener implements Observer<String> { | ||
|
||
@Override | ||
public void accept(ObserverMessage<String> observerMessage) { | ||
ThreadPoolDynamicRefresh dynamicRefresh = new ApolloDynamicThreadPoolChangeHandler(); | ||
dynamicRefresh.registerListener(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>cn.hippo4j</groupId> | ||
<artifactId>hippo4j-agent-plugin</artifactId> | ||
<version>${revision}</version> | ||
</parent> | ||
|
||
<artifactId>hippo4j-agent-nacos-plugin</artifactId> | ||
|
||
<properties> | ||
<nacos.version>2.2.1</nacos.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>cn.hippo4j</groupId> | ||
<artifactId>hippo4j-agent-spring-plugin-common</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>cn.hippo4j</groupId> | ||
<artifactId>hippo4j-threadpool-dynamic-mode-config</artifactId> | ||
<version>${project.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.alibaba.nacos</groupId> | ||
<artifactId>nacos-client</artifactId> | ||
<version>${nacos.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
139 changes: 139 additions & 0 deletions
139
...ugin/src/main/java/cn/hippo4j/agent/plugin/nacos/NacosDynamicThreadPoolChangeHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* | ||
* 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.NacosCloudConfig; | ||
import cn.hippo4j.agent.plugin.spring.common.conf.NacosConfig; | ||
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.common.toolkit.StringUtil; | ||
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.Optional; | ||
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. | ||
* <p> | ||
* 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. | ||
* <p> | ||
*/ | ||
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. | ||
* <p> | ||
* 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 = Optional.ofNullable(NacosCloudConfig.Spring.Cloud.Nacos.Config.SERVER_ADDR).filter(s -> !StringUtil.isEmpty(s)) | ||
.orElse(Optional.ofNullable(NacosConfig.Nacos.Config.SERVER_ADDR).filter(s -> !StringUtil.isEmpty(s)) | ||
.orElse("")); | ||
if (StringUtil.isEmpty(serverAddr)) { | ||
LOGGER.error("[Hippo4j-Agent] add Nacos listener failure. Nacos Registry address not configured"); | ||
return; | ||
} | ||
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<String, Object> changeValueMap = new HashMap<>(); | ||
try { | ||
// Parse the configuration and map the values to the appropriate keys | ||
Map<Object, Object> 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. serverAddr: {} namespace: {} data-id: {} group: {}", serverAddr, namespace, dataId, group); | ||
} catch (Exception e) { | ||
LOGGER.error(e, "[Hippo4j-Agent] Dynamic thread pool refresher, add Nacos listener failure. serverAddr: {} namespace: {} data-id: {} group: {}", serverAddr, namespace, dataId, group); | ||
} | ||
} | ||
|
||
/** | ||
* Builds and binds the {@link BootstrapConfigProperties} from the given configuration map. | ||
* <p> | ||
* 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<Object, Object> configInfo) { | ||
BootstrapConfigProperties bindableBootstrapConfigProperties = SpringPropertyBinder.bindProperties(configInfo, BootstrapConfigProperties.PREFIX, BootstrapConfigProperties.class); | ||
return bindableBootstrapConfigProperties; | ||
} | ||
} |
Oops, something went wrong.