Skip to content

Commit

Permalink
Feat: Agent mode Adapte SpringBoot 1.x , 2.x , 3.x And Adapte Nacos ,…
Browse files Browse the repository at this point in the history
… Apollo Config-Center Agent Plugin (#1573)

* fix: Fixed jar package mounting and startup problem in Agent mode

* Feat: Agent mode adapte SpringBoot 1.x 2.x 3.x And adapte Nacos、Apollo Config-Center

* Fix: Fix build boot3.x moudle jdk17 project error

* Fix: Fix build moudle error

* Fix: Fix build moudle error

* Fix: Fix build moudle error,Upgrade lombok dependency versions and add jaxb dependencies

* Fix: Fix build moudle error,Upgrade maven.compiler.plugin version

* Fix: Fix build moudle error,Upgrade lombok version
  • Loading branch information
Pan-YuJie authored Oct 30, 2024
1 parent a34539f commit b45ff94
Show file tree
Hide file tree
Showing 47 changed files with 1,174 additions and 72 deletions.
1 change: 1 addition & 0 deletions agent/hippo4j-agent-bootstrap/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
Expand Down
15 changes: 9 additions & 6 deletions agent/hippo4j-agent-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<shade.org.slf4j.source>org.slf4j</shade.org.slf4j.source>
<shade.org.slf4j.target>${shade.package}.${shade.org.slf4j.source}</shade.org.slf4j.target>
<ststem-rules.version>1.18.0</ststem-rules.version>
<jaxb.version>2.3.1</jaxb.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -78,15 +79,16 @@
<artifactId>hippo4j-threadpool-infra-common</artifactId>
<version>${project.version}</version>
</dependency>
<!--To fix https://github.com/DozerMapper/dozer/issues/865 -->
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-threadpool-dynamic-mode-config</artifactId>
<version>${project.version}</version>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-threadpool-kernel-monitor</artifactId>
<version>${project.version}</version>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxb.version}</version>
</dependency>
</dependencies>

Expand All @@ -107,6 +109,7 @@
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
import com.ctrip.framework.apollo.model.ConfigChange;
import org.springframework.boot.context.properties.bind.Binder;

import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -72,7 +71,7 @@ public void registerListener() {
/**
* 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
* This method uses SpringPropertyBinder to bind the configuration values to an instance
* of {@link BootstrapConfigProperties}, which can then be used to configure the thread pool
* dynamically.
*
Expand Down
5 changes: 5 additions & 0 deletions agent/hippo4j-agent-plugin/nacos-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
<artifactId>hippo4j-threadpool-dynamic-mode-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import org.springframework.boot.context.properties.bind.Binder;

import java.io.IOException;
import java.util.HashMap;
Expand Down Expand Up @@ -124,7 +123,7 @@ public Executor getExecutor() {
/**
* 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
* This method uses SpringPropertyBinder to bind the configuration values to an instance
* of {@link BootstrapConfigProperties}, which can then be used to configure the thread pool
* dynamically.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws
}

// The Nacos plugin triggers before the Spring configuration plug-in.
// This means that when the Apollo plug-in executes, Spring's Environment is not yet ready,
// This means that when the Nacos plugin executes, Spring's Environment is not yet ready,
// so the configuration cannot be read
// After listening to the AGENT_SPRING_PROPERTIES_LOADER_COMPLETED event, register the listener for Nacos
AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.AGENT_SPRING_PROPERTIES_LOADER_COMPLETED, new NacosConfigPropertiesLoaderCompletedListener());
Expand Down
6 changes: 6 additions & 0 deletions agent/hippo4j-agent-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-agent-core</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down
1 change: 1 addition & 0 deletions agent/hippo4j-agent-plugin/spring-plugins/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<modules>
<module>spring-boot-1x-plugin</module>
<module>spring-boot-2x-plugin</module>
<module>spring-boot-3x-plugin</module>
<module>spring-plugin-common</module>
</modules>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

<properties>
<spring.boot.version>1.5.22.RELEASE</spring.boot.version>
<apollo.version>1.9.1</apollo.version>
</properties>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cn.hippo4j.agent.plugin.spring.boot.v1.boot;

import cn.hippo4j.agent.core.boot.BootService;
import cn.hippo4j.agent.core.boot.DefaultImplementor;
import cn.hippo4j.common.logging.api.ILog;
import cn.hippo4j.common.logging.api.LogManager;

/**
* SpringBoot v1 plugin boot service
*/
@DefaultImplementor
public class SpringBootV1PluginBootService implements BootService {

private static final ILog LOGGER = LogManager.getLogger(SpringBootV1PluginBootService.class);

@Override
public void prepare() throws Throwable {

}

@Override
public void boot() throws Throwable {
LOGGER.info("Loader SpringBootV1PluginBootService...");
}

@Override
public void onComplete() throws Throwable {

}

@Override
public void shutdown() throws Throwable {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
import static net.bytebuddy.matcher.ElementMatchers.named;

/**
* Application Context Refresh instrumentation
* SpringBoot v1 EventPublishingRunListener Finished instrumentation
*/
public class ApplicationContextInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
public class EventPublishingRunListenerInstrumentationV1 extends ClassInstanceMethodsEnhancePluginDefine {

private static final String ENHANCE_CLASS = "org.springframework.context.support.AbstractApplicationContext";
private static final String ENHANCE_CLASS = "org.springframework.boot.context.event.EventPublishingRunListener";

private static final String APPLICATION_CONTEXT_REFRESH_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.boot.v1.interceptor.ApplicationContextInterceptor";
private static final String EVENT_PUBLISHING_FINISHED_INTERCEPTOR_V1 = "cn.hippo4j.agent.plugin.spring.boot.v1.interceptor.EventPublishingRunListenerFinishedInterceptorV1";

@Override
protected ClassMatch enhanceClass() {
Expand All @@ -56,12 +56,12 @@ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("refresh");
return named("finished");
}

@Override
public String getMethodsInterceptor() {
return APPLICATION_CONTEXT_REFRESH_INTERCEPTOR;
return EVENT_PUBLISHING_FINISHED_INTERCEPTOR_V1;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Application Context Refresh interceptor
* EventPublishingRunListener Finished interceptor
*/
public class ApplicationContextInterceptor implements InstanceMethodsAroundInterceptor {
public class EventPublishingRunListenerFinishedInterceptorV1 implements InstanceMethodsAroundInterceptor {

private static final AtomicBoolean isExecuted = new AtomicBoolean(false);

Expand All @@ -46,10 +46,9 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr

@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
// Since the refresh() method is a method of the AbstractApplicationContext class,
// the AbstractApplicationContext itself is an implementation class of the ApplicationContext.
// Therefore, can treat the class instance itself as an ApplicationContext object.
ConfigurableApplicationContext context = (ConfigurableApplicationContext) objInst;
// Since the finished() method is a method of the EventPublishingRunListener class,
// the EventPublishingRunListener the first parameter is ConfigurableApplicationContext
ConfigurableApplicationContext context = (ConfigurableApplicationContext) allArguments[0];
if (context.getParent() != null) {
// After the child container is started, the thread pool registration will be carried out
// IDEA's runtime environment or debugging mechanisms make context refresh speeds different.
Expand All @@ -70,8 +69,12 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA
if (isExecuted.compareAndSet(false, true)) {
ApplicationContextHolder contextHolder = new ApplicationContextHolder();
contextHolder.setApplicationContext(context);
// Load Spring Properties
SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());
AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener());
// register Dynamic ThreadPool Refresh Listener
if (AbstractSubjectCenter.get(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH) == null) {
AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener());
}
}
return ret;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

cn.hippo4j.agent.plugin.spring.boot.v1.boot.SpringBootV1PluginBootService
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.

spring-boot-1.x=cn.hippo4j.agent.plugin.spring.boot.v1.define.ApplicationContextInstrumentation
spring-boot-1.x=cn.hippo4j.agent.plugin.spring.boot.v1.define.EventPublishingRunListenerInstrumentationV1
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import cn.hippo4j.common.logging.api.LogManager;

/**
* SpringBoot v1 plugin boot service
* SpringBoot v2 plugin boot service
*/
@DefaultImplementor
public class SpringBootV2PluginBootService implements BootService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;

import java.util.Collections;
import java.util.Arrays;
import java.util.List;

import static net.bytebuddy.matcher.ElementMatchers.named;
import static cn.hippo4j.agent.core.plugin.match.NameMatch.byName;
import static net.bytebuddy.matcher.ElementMatchers.not;

/**
* Event publishing run listener instrumentation
* SpringBoot v2 Event publishing run listener instrumentation
*/
public class EventPublishingRunListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
public class EventPublishingRunListenerInstrumentationV2 extends ClassInstanceMethodsEnhancePluginDefine {

private static final String ENHANCE_CLASS = "org.springframework.boot.context.event.EventPublishingRunListener";

private static final String EVENT_PUBLISHING_FINISHED_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.boot.v2.interceptor.EventPublishingStartedInterceptor";
private static final String EVENT_PUBLISHING_STARTED_INTERCEPTOR_V2 = "cn.hippo4j.agent.plugin.spring.boot.v2.interceptor.EventPublishingStartedInterceptorV2";
private static final String EVENT_PUBLISHING_ENVIRONMENT_PREPARED_INTERCEPTOR = "cn.hippo4j.agent.plugin.spring.common.interceptor.EventPublishingRunListenerEnvironmentPreparedInterceptor";

@Override
Expand All @@ -63,7 +64,7 @@ public ElementMatcher<MethodDescription> getMethodsMatcher() {

@Override
public String getMethodsInterceptor() {
return EVENT_PUBLISHING_FINISHED_INTERCEPTOR;
return EVENT_PUBLISHING_STARTED_INTERCEPTOR_V2;
}

@Override
Expand Down Expand Up @@ -93,7 +94,17 @@ public boolean isOverrideArgs() {

@Override
protected List<WitnessMethod> witnessMethods() {
return Collections.singletonList(new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener",
named("started")));
return Arrays.asList(
new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", named("started")),
new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", named("running")),
new WitnessMethod("org.springframework.boot.context.event.EventPublishingRunListener", not(named("ready")))
// new WitnessMethod("org.springframework.boot.context.properties.ConstructorBinding", not(isAnnotatedWith(Deprecated.class)))
);
}

@Override
protected String[] witnessClasses() {
return new String[]{"org.springframework.boot.context.properties.ConstructorBinding"};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
/**
* Event publishing started interceptor
*/
public class EventPublishingStartedInterceptor implements InstanceMethodsAroundInterceptor {
public class EventPublishingStartedInterceptorV2 implements InstanceMethodsAroundInterceptor {

private static final AtomicBoolean isExecuted = new AtomicBoolean(false);

private static final ILog LOGGER = LogManager.getLogger(EventPublishingStartedInterceptor.class);
private static final ILog LOGGER = LogManager.getLogger(EventPublishingStartedInterceptorV2.class);

@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
Expand All @@ -61,7 +61,9 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA
// Load Spring Properties
SpringPropertiesLoader.loadSpringProperties(context.getEnvironment());
// register Dynamic ThreadPool Refresh Listener
AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener());
if (AbstractSubjectCenter.get(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH) == null) {
AbstractSubjectCenter.register(AbstractSubjectCenter.SubjectType.THREAD_POOL_DYNAMIC_REFRESH, new DynamicThreadPoolRefreshListener());
}
}

return ret;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.

spring-boot-2.x=cn.hippo4j.agent.plugin.spring.boot.v2.define.EventPublishingRunListenerInstrumentation
spring-boot-2.x=cn.hippo4j.agent.plugin.spring.boot.v2.define.EventPublishingRunListenerInstrumentationV2
Loading

0 comments on commit b45ff94

Please sign in to comment.