From ab4585b06f0b4a844a7ea750a0e4e326361dbc5b Mon Sep 17 00:00:00 2001 From: provenceee <83857838+provenceee@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:53:35 +0800 Subject: [PATCH] *support springboot3 Signed-off-by: provenceee <83857838+provenceee@users.noreply.github.com> --- .../sermant/core/AgentCoreEntrance.java | 3 +- .../sermant/core/common/LoggerFactory.java | 2 +- .../declarer/DispatcherServletDeclarer.java | 49 ++++++++ .../DiscoveryManagerInterceptor.java | 2 +- .../DispatcherServletInterceptor.java | 117 ++++++++++++++++++ .../EurekaHttpClientInterceptor.java | 2 +- .../ServiceRegistryInterceptor.java | 2 +- .../spring/utils/SpringRouterUtils.java | 52 ++++++++ ....core.plugin.agent.declarer.PluginDeclarer | 3 +- .../DiscoveryManagerInterceptorTest.java | 9 -- .../EurekaHttpClientInterceptorTest.java | 9 -- .../ServiceRegistryInterceptorTest.java | 9 -- 12 files changed, 226 insertions(+), 33 deletions(-) create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/DispatcherServletDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DispatcherServletInterceptor.java diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java index 88fe80321a..614a4b6242 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/AgentCoreEntrance.java @@ -85,11 +85,12 @@ public static void install(String artifact, Map argsMap, Instrum agentType = AgentType.AGENTMAIN.getValue(); } artifactCache = artifact; - adviserCache = new DefaultAdviser(); // 初始化默认日志,在未加载日志引擎前保证日志可用 LoggerFactory.initDefaultLogger(artifact); + adviserCache = new DefaultAdviser(); + // 初始化框架类加载器 ClassLoaderManager.init(argsMap); diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/common/LoggerFactory.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/common/LoggerFactory.java index d8bae1bc12..b63cfbb1ed 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/common/LoggerFactory.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/common/LoggerFactory.java @@ -92,7 +92,7 @@ public static Logger getLogger() { if (defaultLogger == null) { synchronized (LoggerFactory.class) { if (defaultLogger == null) { - defaultLogger = java.util.logging.Logger.getLogger("sermant"); + defaultLogger = java.util.logging.Logger.getLogger("sermant.default"); } } } diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/DispatcherServletDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/DispatcherServletDeclarer.java new file mode 100644 index 0000000000..1b7aaf2fc4 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/DispatcherServletDeclarer.java @@ -0,0 +1,49 @@ +/* + * + * * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * * + * * Licensed 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 com.huaweicloud.sermant.router.spring.declarer; + +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; + +/** + * 获取http请求数据 + * + * @author provenceee + * @since 2024-11-11 + */ +public class DispatcherServletDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS + = "org.springframework.web.servlet.DispatcherServlet"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.DispatcherServletInterceptor"; + + private static final String METHOD_NAME = "doService"; + + /** + * 构造方法 + */ + public DispatcherServletDeclarer() { + super(ENHANCE_CLASS, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } +} diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptor.java index 43272c464f..92acb2e00e 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptor.java @@ -59,6 +59,7 @@ public ExecuteContext before(ExecuteContext context) { Object serviceName = ReflectUtils.getFieldValue(obj, "serviceName").orElse(null); if (serviceName instanceof String) { AppCache.INSTANCE.setAppName((String) serviceName); + configService.init(RouterConstant.SPRING_CACHE_NAME, (String) serviceName); } else { LOGGER.warning("Service name is null or not instanceof string."); } @@ -69,7 +70,6 @@ public ExecuteContext before(ExecuteContext context) { @Override public ExecuteContext after(ExecuteContext context) { - configService.init(RouterConstant.SPRING_CACHE_NAME, AppCache.INSTANCE.getAppName()); return context; } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DispatcherServletInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DispatcherServletInterceptor.java new file mode 100644 index 0000000000..ab4cc358cd --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/DispatcherServletInterceptor.java @@ -0,0 +1,117 @@ +/* + * + * * Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved. + * * + * * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; +import com.huaweicloud.sermant.core.plugin.service.PluginServiceManager; +import com.huaweicloud.sermant.router.common.handler.Handler; +import com.huaweicloud.sermant.router.common.utils.CollectionUtils; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.spring.handler.AbstractRequestTagHandler; +import com.huaweicloud.sermant.router.spring.handler.AbstractRequestTagHandler.Keys; +import com.huaweicloud.sermant.router.spring.handler.LaneRequestTagHandler; +import com.huaweicloud.sermant.router.spring.handler.RouteRequestTagHandler; +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; +import com.huaweicloud.sermant.router.spring.utils.SpringRouterUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 获取http请求数据 + * + * @author provenceee + * @since 2024-11-11 + */ +public class DispatcherServletInterceptor extends AbstractInterceptor { + private final List handlers; + + private final SpringConfigService configService; + + /** + * 构造方法 + */ + public DispatcherServletInterceptor() { + configService = PluginServiceManager.getPluginService(SpringConfigService.class); + handlers = new ArrayList<>(); + handlers.add(new LaneRequestTagHandler()); + handlers.add(new RouteRequestTagHandler()); + handlers.sort(Comparator.comparingInt(Handler::getOrder)); + } + + @Override + public ExecuteContext before(ExecuteContext context) { + Set matchKeys = configService.getMatchKeys(); + Set injectTags = configService.getInjectTags(); + if (CollectionUtils.isEmpty(matchKeys) && CollectionUtils.isEmpty(injectTags)) { + // 染色标记为空,代表没有染色规则,直接return + return context; + } + Object request = context.getArguments()[0]; + Map> headers = getHeaders(request); + Map parameterMap = SpringRouterUtils.getParameterMap(request); + String path = SpringRouterUtils.getRequestUri(request); + String method = SpringRouterUtils.getMethod(request); + handlers.forEach(handler -> ThreadLocalUtils.addRequestTag( + handler.getRequestTag(path, method, headers, parameterMap, new Keys(matchKeys, injectTags)))); + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestTag(); + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestTag(); + return context; + } + + private Map> getHeaders(Object request) { + Map> headers = new HashMap<>(); + Enumeration enumeration = SpringRouterUtils.getHeaderNames(request); + while (enumeration.hasMoreElements()) { + String key = (String) enumeration.nextElement(); + headers.put(key, enumeration2List(SpringRouterUtils.getHeaders(request, key))); + } + return headers; + } + + private List enumeration2List(Enumeration enumeration) { + if (enumeration == null) { + return Collections.emptyList(); + } + List collection = new ArrayList<>(); + while (enumeration.hasMoreElements()) { + collection.add((String) enumeration.nextElement()); + } + return collection; + } +} diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptor.java index 375c4eb43d..a74f9fb490 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptor.java @@ -53,6 +53,7 @@ public ExecuteContext before(ExecuteContext context) { if (argument instanceof InstanceInfo) { InstanceInfo instanceInfo = (InstanceInfo) argument; AppCache.INSTANCE.setAppName(instanceInfo.getAppName()); + configService.init(RouterConstant.SPRING_CACHE_NAME, instanceInfo.getAppName()); SpringRouterUtils.putMetaData(instanceInfo.getMetadata(), routerConfig); } return context; @@ -60,7 +61,6 @@ public ExecuteContext before(ExecuteContext context) { @Override public ExecuteContext after(ExecuteContext context) { - configService.init(RouterConstant.SPRING_CACHE_NAME, AppCache.INSTANCE.getAppName()); return context; } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java index be1498b366..6003f4e685 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java @@ -66,6 +66,7 @@ public ExecuteContext before(ExecuteContext context) { serviceRegistration.getClass().getDeclaredMethod("getRegistration")) .invoke(serviceRegistration); AppCache.INSTANCE.setAppName(registration.getServiceId()); + configService.init(RouterConstant.SPRING_CACHE_NAME, registration.getServiceId()); SpringRouterUtils.putMetaData(registration.getMetadata(), routerConfig); } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException ex) { LOGGER.log(Level.WARNING, "Can not get the registration.", ex); @@ -76,7 +77,6 @@ public ExecuteContext before(ExecuteContext context) { @Override public ExecuteContext after(ExecuteContext context) { - configService.init(RouterConstant.SPRING_CACHE_NAME, AppCache.INSTANCE.getAppName()); return context; } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/utils/SpringRouterUtils.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/utils/SpringRouterUtils.java index 951f1c0efd..e5e1b75aac 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/utils/SpringRouterUtils.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/utils/SpringRouterUtils.java @@ -22,6 +22,7 @@ import com.huaweicloud.sermant.router.common.utils.ReflectUtils; import com.huaweicloud.sermant.router.spring.cache.AppCache; +import java.util.Enumeration; import java.util.Locale; import java.util.Map; @@ -39,6 +40,57 @@ public class SpringRouterUtils { private SpringRouterUtils() { } + /** + * 获取请求中的parameter + * + * @param obj HttpServletRequest + * @return parameter + */ + public static Map getParameterMap(Object obj) { + return (Map) ReflectUtils.invokeWithNoneParameter(obj, "getParameterMap"); + } + + /** + * 获取请求中的uri + * + * @param obj HttpServletRequest + * @return uri + */ + public static String getRequestUri(Object obj) { + return ReflectUtils.invokeWithNoneParameterAndReturnString(obj, "getRequestURI"); + } + + /** + * 获取请求中的方法 + * + * @param obj HttpServletRequest + * @return method + */ + public static String getMethod(Object obj) { + return ReflectUtils.invokeWithNoneParameterAndReturnString(obj, "getMethod"); + } + + /** + * 获取请求中的所有请求头的key + * + * @param obj HttpServletRequest + * @return key + */ + public static Enumeration getHeaderNames(Object obj) { + return (Enumeration) ReflectUtils.invokeWithNoneParameter(obj, "getHeaderNames"); + } + + /** + * 获取元数据 + * + * @param obj HttpServletRequest + * @param key header key + * @return 元数据 + */ + public static Enumeration getHeaders(Object obj, String key) { + return (Enumeration) ReflectUtils.invokeWithParameter(obj, "getHeaders", key, String.class); + } + /** * 获取元数据 * diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-router/spring-router-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer index 53a7e3cfbf..57b5c16a8f 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -2,9 +2,10 @@ com.huaweicloud.sermant.router.spring.declarer.AbstractHandlerMappingDeclarer com.huaweicloud.sermant.router.spring.declarer.BaseLoadBalancerDeclarer com.huaweicloud.sermant.router.spring.declarer.ClientHttpRequestDeclarer com.huaweicloud.sermant.router.spring.declarer.DiscoveryManagerDeclarer +com.huaweicloud.sermant.router.spring.declarer.DispatcherServletDeclarer com.huaweicloud.sermant.router.spring.declarer.EurekaHttpClientDeclarer com.huaweicloud.sermant.router.spring.declarer.FeignClientDeclarer -com.huaweicloud.sermant.router.spring.declarer.HandlerExecutionChainDeclarer +#com.huaweicloud.sermant.router.spring.declarer.HandlerExecutionChainDeclarer com.huaweicloud.sermant.router.spring.declarer.HystrixActionDeclarer com.huaweicloud.sermant.router.spring.declarer.LoadBalancerClientFilterDeclarer com.huaweicloud.sermant.router.spring.declarer.NopInstanceFilterDeclarer diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptorTest.java index dcf6e5111d..b1546a960a 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/DiscoveryManagerInterceptorTest.java @@ -104,15 +104,6 @@ public void testBefore() { context.getArguments()[0] = new TestObject(null); interceptor.before(context); Assert.assertEquals("foo", AppCache.INSTANCE.getAppName()); - } - - /** - * 测试after方法 - */ - @Test - public void testAfter() { - AppCache.INSTANCE.setAppName("foo"); - interceptor.after(context); Assert.assertEquals(RouterConstant.SPRING_CACHE_NAME, configService.getCacheName()); Assert.assertEquals("foo", configService.getServiceName()); } diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java index 9d858a0d4d..8c82b6def2 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java @@ -111,15 +111,6 @@ public void testBefore() { Assert.assertEquals(routerConfig.getRouterVersion(), metadata.get("version")); Assert.assertEquals("bar1", metadata.get("bar")); Assert.assertEquals("foo2", metadata.get("foo")); - } - - /** - * 测试after方法 - */ - @Test - public void testAfter() { - AppCache.INSTANCE.setAppName("FOO"); - interceptor.after(context); Assert.assertEquals(RouterConstant.SPRING_CACHE_NAME, configService.getCacheName()); Assert.assertEquals("FOO", configService.getServiceName()); } diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java index 8b8249da8e..842b50ef73 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java @@ -105,15 +105,6 @@ public void testBefore() { Assert.assertEquals(routerConfig.getRouterVersion(), metadata.get("version")); Assert.assertEquals("bar1", metadata.get("bar")); Assert.assertEquals("foo2", metadata.get("foo")); - } - - /** - * 测试after方法 - */ - @Test - public void testAfter() { - AppCache.INSTANCE.setAppName("foo"); - interceptor.after(context); Assert.assertEquals(RouterConstant.SPRING_CACHE_NAME, configService.getCacheName()); Assert.assertEquals("foo", configService.getServiceName()); }