From eb012fb15bde1a07e721e6b1e2730f775c96dba7 Mon Sep 17 00:00:00 2001 From: provenceee <83857838+provenceee@users.noreply.github.com> Date: Sat, 12 Aug 2023 11:49:08 +0800 Subject: [PATCH] =?UTF-8?q?*=E5=A2=9E=E5=8A=A0=E8=B7=A8=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E4=BC=A0=E9=80=92=E6=95=B0=E6=8D=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/config.properties | 2 +- .../config/test/config.properties | 2 +- .../plugin/agent/matcher/MethodMatcher.java | 9 ++ .../core/plugin/agent/matcher/MethodType.java | 9 ++ sermant-common/pom.xml | 3 + .../src/main/resources/application.yml | 2 +- .../source/SpringEventPublisherTest.java | 24 +++- .../sermant-router/config/config.yaml | 7 + .../ContextFilterInterceptorTest.java | 9 ++ .../service/AbstractDirectoryServiceTest.java | 3 + sermant-plugins/sermant-router/pom.xml | 3 + .../router/common/config/TransmitConfig.java | 72 +++++++++++ .../router/common/request/RequestData.java | 9 ++ .../router/common/request/RequestHeader.java | 7 + .../router/common/utils/ThreadLocalUtils.java | 17 ++- ...ud.sermant.core.plugin.config.PluginConfig | 1 + .../router-transmit-plugin/pom.xml | 65 ++++++++++ .../transmit/declarer/ExecutorDeclarer.java | 58 +++++++++ .../ScheduledExecutorServiceDeclarer.java | 58 +++++++++ .../AbstractExecutorInterceptor.java | 120 ++++++++++++++++++ .../interceptor/ExecutorInterceptor.java | 35 +++++ .../ScheduledExecutorServiceInterceptor.java | 35 +++++ .../wrapper/AbstractThreadWrapper.java | 120 ++++++++++++++++++ .../transmit/wrapper/CallableWrapper.java | 44 +++++++ .../wrapper/RunnableAndCallableWrapper.java | 45 +++++++ .../transmit/wrapper/RunnableWrapper.java | 42 ++++++ ....core.plugin.agent.declarer.PluginDeclarer | 2 + .../sermant/router/transmit/BaseTest.java | 50 ++++++++ .../router/transmit/RunnableAndCallable.java | 34 +++++ .../interceptor/ExecutorInterceptorTest.java | 101 +++++++++++++++ ...heduledExecutorServiceInterceptorTest.java | 102 +++++++++++++++ .../transmit/wrapper/CallableWrapperTest.java | 77 +++++++++++ .../RunnableAndCallableWrapperTest.java | 116 +++++++++++++++++ .../transmit/wrapper/RunnableWrapperTest.java | 73 +++++++++++ .../spring-router-plugin/pom.xml | 13 ++ .../spring/declarer/ControllerDeclarer.java | 70 ---------- .../declarer/HttpServerHandleDeclarer.java | 48 +++++++ .../HttpServerOperationsDeclarer.java | 47 +++++++ .../declarer/HystrixActionDeclarer.java | 7 + .../LoadBalancerClientFilterDeclarer.java | 5 +- .../spring/declarer/LoadBalancerDeclarer.java | 54 ++++++++ ...ctiveLoadBalancerClientFilterDeclarer.java | 47 +++++++ .../declarer/ReactiveTypeHandlerDeclarer.java | 48 +++++++ .../ServiceInstanceListSupplierDeclarer.java | 7 + .../declarer/WebClientBuilderDeclarer.java | 47 +++++++ .../AbstractHandlerMappingInterceptor.java | 6 +- .../EurekaHttpClientInterceptor.java | 7 + .../interceptor/FeignClientInterceptor.java | 5 + .../HttpServerHandleInterceptor.java | 64 ++++++++++ ...a => HttpServerOperationsInterceptor.java} | 11 +- .../LoadBalancerClientFilterInterceptor.java | 17 +-- .../interceptor/LoadBalancerInterceptor.java | 85 +++++++++++++ ...veLoadBalancerClientFilterInterceptor.java | 72 +++++++++++ .../ReactiveTypeHandlerInterceptor.java | 49 +++++++ .../RouterExchangeFilterFunction.java | 55 ++++++++ .../WebClientBuilderInterceptor.java | 82 ++++++++++++ ....core.plugin.agent.declarer.PluginDeclarer | 9 +- .../router/spring/BaseTransmitConfigTest.java | 53 ++++++++ ...AbstractHandlerMappingInterceptorTest.java | 3 +- .../BaseLoadBalancerInterceptorTest.java | 3 + .../ClientHttpRequestInterceptorTest.java | 3 +- .../ControllerInterceptorTest.java | 77 ----------- .../EurekaHttpClientInterceptorTest.java | 40 ++++++ .../FeignClientInterceptorTest.java | 3 + .../HystrixActionInterceptorTest.java | 13 +- ...adBalancerClientFilterInterceptorTest.java | 3 +- .../NopInstanceFilterInterceptorTest.java | 3 + ...ceInstanceListSupplierInterceptorTest.java | 3 + 68 files changed, 2232 insertions(+), 183 deletions(-) create mode 100644 sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/TransmitConfig.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/pom.xml create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ExecutorDeclarer.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ScheduledExecutorServiceDeclarer.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/AbstractExecutorInterceptor.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptor.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptor.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/AbstractThreadWrapper.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapper.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapper.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapper.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/BaseTest.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/RunnableAndCallable.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptorTest.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptorTest.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapperTest.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapperTest.java create mode 100644 sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapperTest.java delete mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ControllerDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerHandleDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerOperationsDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveLoadBalancerClientFilterDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveTypeHandlerDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/WebClientBuilderDeclarer.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerHandleInterceptor.java rename sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/{ControllerInterceptor.java => HttpServerOperationsInterceptor.java} (75%) create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerInterceptor.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ReactiveLoadBalancerClientFilterInterceptor.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ReactiveTypeHandlerInterceptor.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouterExchangeFilterFunction.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/WebClientBuilderInterceptor.java create mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/BaseTransmitConfigTest.java delete mode 100644 sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ControllerInterceptorTest.java diff --git a/sermant-agentcore/sermant-agentcore-config/config/config.properties b/sermant-agentcore/sermant-agentcore-config/config/config.properties index 296af1d292..aec854e3cf 100644 --- a/sermant-agentcore/sermant-agentcore-config/config/config.properties +++ b/sermant-agentcore/sermant-agentcore-config/config/config.properties @@ -1,5 +1,5 @@ # agent config -agent.config.isEnhanceBootStrapEnable=false +agent.config.isEnhanceBootStrapEnable=true agent.config.ignoredPrefixes=com.huawei.sermant,com.huaweicloud.sermant agent.config.ignoredInterfaces=org.springframework.cglib.proxy.Factory agent.config.combineStrategy=ALL diff --git a/sermant-agentcore/sermant-agentcore-config/config/test/config.properties b/sermant-agentcore/sermant-agentcore-config/config/test/config.properties index 296af1d292..aec854e3cf 100644 --- a/sermant-agentcore/sermant-agentcore-config/config/test/config.properties +++ b/sermant-agentcore/sermant-agentcore-config/config/test/config.properties @@ -1,5 +1,5 @@ # agent config -agent.config.isEnhanceBootStrapEnable=false +agent.config.isEnhanceBootStrapEnable=true agent.config.ignoredPrefixes=com.huawei.sermant,com.huaweicloud.sermant agent.config.ignoredInterfaces=org.springframework.cglib.proxy.Factory agent.config.combineStrategy=ALL diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodMatcher.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodMatcher.java index b47f53ff28..3024aff3c6 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodMatcher.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodMatcher.java @@ -238,6 +238,15 @@ public static MethodMatcher isMemberMethod() { return methodTypeMatches(MethodType.MEMBER); } + /** + * 匹配公有方法,见{@link #methodTypeMatches} + * + * @return 方法匹配器对象 + */ + public static MethodMatcher isPublicMethod() { + return methodTypeMatches(MethodType.PUBLIC); + } + /** * 匹配符合类型的方法,包括静态方法,构造函数和成员方法三种 * diff --git a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodType.java b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodType.java index a78378669a..524aa929fc 100644 --- a/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodType.java +++ b/sermant-agentcore/sermant-agentcore-core/src/main/java/com/huaweicloud/sermant/core/plugin/agent/matcher/MethodType.java @@ -52,6 +52,15 @@ public boolean match(MethodDescription methodDescription) { public boolean match(MethodDescription methodDescription) { return !methodDescription.isStatic() && !methodDescription.isConstructor(); } + }, + /** + * 公有方法 + */ + PUBLIC() { + @Override + public boolean match(MethodDescription methodDescription) { + return methodDescription.isPublic(); + } }; /** diff --git a/sermant-common/pom.xml b/sermant-common/pom.xml index 365eab5281..9bbb25267d 100644 --- a/sermant-common/pom.xml +++ b/sermant-common/pom.xml @@ -33,6 +33,9 @@ agent + + true + diff --git a/sermant-integration-tests/spring-test/spring-common-demos/spring-common-zuul/src/main/resources/application.yml b/sermant-integration-tests/spring-test/spring-common-demos/spring-common-zuul/src/main/resources/application.yml index 8d8c1e5a01..1246e8fd65 100644 --- a/sermant-integration-tests/spring-test/spring-common-demos/spring-common-zuul/src/main/resources/application.yml +++ b/sermant-integration-tests/spring-test/spring-common-demos/spring-common-zuul/src/main/resources/application.yml @@ -20,7 +20,7 @@ hystrix: execution: isolation: thread: - timeoutInMilliseconds: 10000 + timeoutInMilliseconds: 50000 ribbon: ConnectTimeout: 10000 diff --git a/sermant-plugins/sermant-dynamic-config/dynamic-config-plugin/src/test/java/com/huawei/dynamic/config/source/SpringEventPublisherTest.java b/sermant-plugins/sermant-dynamic-config/dynamic-config-plugin/src/test/java/com/huawei/dynamic/config/source/SpringEventPublisherTest.java index 6d191278f4..82090ded37 100644 --- a/sermant-plugins/sermant-dynamic-config/dynamic-config-plugin/src/test/java/com/huawei/dynamic/config/source/SpringEventPublisherTest.java +++ b/sermant-plugins/sermant-dynamic-config/dynamic-config-plugin/src/test/java/com/huawei/dynamic/config/source/SpringEventPublisherTest.java @@ -20,10 +20,15 @@ import com.huawei.dynamic.config.DynamicConfiguration; import com.huawei.dynamic.config.RefreshNotifier; +import com.huaweicloud.sermant.core.operation.OperationManager; +import com.huaweicloud.sermant.core.operation.converter.api.YamlConverter; import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEvent; import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEventType; +import com.huaweicloud.sermant.implement.operation.converter.YamlConverterImpl; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockedStatic; @@ -38,15 +43,30 @@ * @since 2022-09-05 */ public class SpringEventPublisherTest { + private MockedStatic operationManagerMockedStatic; + @Mock private ApplicationEventPublisher applicationEventPublisher; + @Before + public void setUp() { + operationManagerMockedStatic = Mockito.mockStatic(OperationManager.class); + operationManagerMockedStatic.when(() -> OperationManager.getOperation(YamlConverter.class)) + .thenReturn(new YamlConverterImpl()); + } + + @After + public void tearDown() { + operationManagerMockedStatic.close(); + } + @Test public void test() { MockitoAnnotations.openMocks(this); - try (final MockedStatic pluginConfigManagerMockedStatic = Mockito.mockStatic(PluginConfigManager.class)){ + try (final MockedStatic pluginConfigManagerMockedStatic = Mockito + .mockStatic(PluginConfigManager.class)) { pluginConfigManagerMockedStatic.when(() -> PluginConfigManager.getPluginConfig(DynamicConfiguration.class)) - .thenReturn(new DynamicConfiguration()); + .thenReturn(new DynamicConfiguration()); final SpringEventPublisher springEventPublisher = new SpringEventPublisher(); springEventPublisher.setApplicationEventPublisher(applicationEventPublisher); final OriginConfigCenterDisableListenerTest originConfigCenterDisableListenerTest = new OriginConfigCenterDisableListenerTest(); diff --git a/sermant-plugins/sermant-router/config/config.yaml b/sermant-plugins/sermant-router/config/config.yaml index 6ff46bbcd1..5bc03adf43 100644 --- a/sermant-plugins/sermant-router/config/config.yaml +++ b/sermant-plugins/sermant-router/config/config.yaml @@ -13,3 +13,10 @@ router.plugin: request-tags: [] # 需要解析的请求头的tag parse-header-tag: '' +transmit.plugin: + # 是否在直接new Thread时传递标签 + enabled-thread: true + # 是否在非定时线程池中传递标签 + enabled-thread-pool: true + # 是否在定时线程池的schedule/scheduleAtFixedRate/scheduleWithFixedDelay方法中传递标签 + enabled-scheduler: false diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptorTest.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptorTest.java index 2455f1849f..a8d08986bd 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptorTest.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/interceptor/ContextFilterInterceptorTest.java @@ -17,7 +17,9 @@ package com.huaweicloud.sermant.router.dubbo.interceptor; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; import com.huaweicloud.sermant.router.dubbo.service.DubboConfigService; @@ -50,6 +52,8 @@ public class ContextFilterInterceptorTest { private static MockedStatic mockServiceManager; + private static MockedStatic mockPluginConfigManager; + /** * UT执行前进行mock */ @@ -70,6 +74,10 @@ public Set getMatchKeys() { return keys; } }); + + mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); } /** @@ -78,6 +86,7 @@ public Set getMatchKeys() { @AfterClass public static void after() { mockServiceManager.close(); + mockPluginConfigManager.close(); } public ContextFilterInterceptorTest() throws NoSuchMethodException { diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java index a8927c5333..1a5b8ac849 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java @@ -19,6 +19,7 @@ import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.utils.StringUtils; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.constants.RouterConstant; import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; @@ -77,6 +78,8 @@ public static void before() { mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(RouterConfig.class)) .thenReturn(config); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); service = new AbstractDirectoryServiceImpl(); } diff --git a/sermant-plugins/sermant-router/pom.xml b/sermant-plugins/sermant-router/pom.xml index 9e28342e16..b28c030c1c 100644 --- a/sermant-plugins/sermant-router/pom.xml +++ b/sermant-plugins/sermant-router/pom.xml @@ -33,6 +33,7 @@ router-common router-config-common router-config-service + router-transmit-plugin spring-router-plugin spring-router-service @@ -45,6 +46,7 @@ router-common router-config-common router-config-service + router-transmit-plugin spring-router-plugin spring-router-service @@ -57,6 +59,7 @@ router-common router-config-common router-config-service + router-transmit-plugin spring-router-plugin spring-router-service diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/TransmitConfig.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/TransmitConfig.java new file mode 100644 index 0000000000..2049aea873 --- /dev/null +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/TransmitConfig.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021-2022 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.common.config; + +import com.huaweicloud.sermant.core.config.common.ConfigFieldKey; +import com.huaweicloud.sermant.core.config.common.ConfigTypeKey; +import com.huaweicloud.sermant.core.plugin.config.PluginConfig; + +/** + * 路由配置 + * + * @author provenceee + * @since 2021-11-18 + */ +@ConfigTypeKey("transmit.plugin") +public class TransmitConfig implements PluginConfig { + /** + * 是否在直接new Thread时传递标签 + */ + @ConfigFieldKey("enabled-thread") + private boolean enabledThread; + + /** + * 是否在非定时线程池中传递标签 + */ + @ConfigFieldKey("enabled-thread-pool") + private boolean enabledThreadPool; + + /** + * 是否在定时线程池的schedule/scheduleAtFixedRate/scheduleWithFixedDelay方法中传递标签 + */ + @ConfigFieldKey("enabled-scheduler") + private boolean enabledScheduler; + + public boolean isEnabledThread() { + return enabledThread; + } + + public void setEnabledThread(boolean enabledThread) { + this.enabledThread = enabledThread; + } + + public boolean isEnabledThreadPool() { + return enabledThreadPool; + } + + public void setEnabledThreadPool(boolean enabledThreadPool) { + this.enabledThreadPool = enabledThreadPool; + } + + public boolean isEnabledScheduler() { + return enabledScheduler; + } + + public void setEnabledScheduler(boolean enabledScheduler) { + this.enabledScheduler = enabledScheduler; + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestData.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestData.java index ea6894d9e8..84c186b538 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestData.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestData.java @@ -50,4 +50,13 @@ public String getPath() { public String getHttpMethod() { return httpMethod; } + + @Override + public String toString() { + return "{" + + "path='" + path + '\'' + + ", httpMethod='" + httpMethod + '\'' + + ", header='" + getHeader() + '\'' + + '}'; + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestHeader.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestHeader.java index d6ff8997e1..0a320652a7 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestHeader.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/request/RequestHeader.java @@ -42,4 +42,11 @@ public RequestHeader(Map> header) { public Map> getHeader() { return Optional.ofNullable(header).orElse(Collections.emptyMap()); } + + @Override + public String toString() { + return "{" + + "header='" + getHeader() + '\'' + + '}'; + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ThreadLocalUtils.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ThreadLocalUtils.java index 7f7860c964..8e65cba5cf 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ThreadLocalUtils.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ThreadLocalUtils.java @@ -16,6 +16,8 @@ package com.huaweicloud.sermant.router.common.utils; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.request.RequestHeader; @@ -26,13 +28,24 @@ * @since 2022-07-08 */ public class ThreadLocalUtils { - private static final ThreadLocal HEADER = new ThreadLocal<>(); + private static final ThreadLocal HEADER; - private static final ThreadLocal DATA = new ThreadLocal<>(); + private static final ThreadLocal DATA; private ThreadLocalUtils() { } + static { + TransmitConfig transmitConfig = PluginConfigManager.getPluginConfig(TransmitConfig.class); + if (transmitConfig.isEnabledThread()) { + HEADER = new InheritableThreadLocal<>(); + DATA = new InheritableThreadLocal<>(); + } else { + HEADER = new ThreadLocal<>(); + DATA = new ThreadLocal<>(); + } + } + /** * 获取线程变量 * diff --git a/sermant-plugins/sermant-router/router-common/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.config.PluginConfig b/sermant-plugins/sermant-router/router-common/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.config.PluginConfig index 9074549e1a..986a4c44ff 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.config.PluginConfig +++ b/sermant-plugins/sermant-router/router-common/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.config.PluginConfig @@ -3,3 +3,4 @@ # com.huaweicloud.sermant.router.common.config.RouterConfig +com.huaweicloud.sermant.router.common.config.TransmitConfig diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/pom.xml b/sermant-plugins/sermant-router/router-transmit-plugin/pom.xml new file mode 100644 index 0000000000..3ad78451f1 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/pom.xml @@ -0,0 +1,65 @@ + + + + sermant-router + com.huaweicloud.sermant + 1.0.0 + + 4.0.0 + + router-transmit-plugin + + + 8 + 8 + UTF-8 + plugin + + + + + com.huaweicloud.sermant + sermant-agentcore-core + provided + + + com.huaweicloud.sermant + router-common + ${project.version} + + + junit + junit + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-inline + test + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ExecutorDeclarer.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ExecutorDeclarer.java new file mode 100644 index 0000000000..f28795254a --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ExecutorDeclarer.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023-2023 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.transmit.declarer; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +/** + * 拦截Executor + * + * @author provenceee + * @since 2023-04-20 + */ +public class ExecutorDeclarer extends AbstractPluginDeclarer { + private static final String ENHANCE_CLASS = "java.util.concurrent.Executor"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.transmit.interceptor.ExecutorInterceptor"; + + private static final String[] METHOD_NAME = {"execute", "submit"}; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.isExtendedFrom(ENHANCE_CLASS); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameContains(METHOD_NAME).and(MethodMatcher.isPublicMethod()), + INTERCEPT_CLASS) + }; + } + + @Override + public boolean isEnabled() { + TransmitConfig pluginConfig = PluginConfigManager.getPluginConfig(TransmitConfig.class); + return pluginConfig.isEnabledThread() || pluginConfig.isEnabledThreadPool(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ScheduledExecutorServiceDeclarer.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ScheduledExecutorServiceDeclarer.java new file mode 100644 index 0000000000..eb563c4c8e --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/declarer/ScheduledExecutorServiceDeclarer.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023-2023 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.transmit.declarer; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +/** + * ScheduledExecutorService拦截点 + * + * @author provenceee + * @since 2023-06-07 + */ +public class ScheduledExecutorServiceDeclarer extends AbstractPluginDeclarer { + private static final String ENHANCE_CLASS = "java.util.concurrent.ScheduledExecutorService"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.transmit.interceptor.ScheduledExecutorServiceInterceptor"; + + private static final String[] METHOD_NAME = {"schedule", "scheduleAtFixedRate", "scheduleWithFixedDelay"}; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.isExtendedFrom(ENHANCE_CLASS); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameContains(METHOD_NAME).and(MethodMatcher.isPublicMethod()), + INTERCEPT_CLASS) + }; + } + + @Override + public boolean isEnabled() { + TransmitConfig pluginConfig = PluginConfigManager.getPluginConfig(TransmitConfig.class); + return pluginConfig.isEnabledThread() || pluginConfig.isEnabledScheduler(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/AbstractExecutorInterceptor.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/AbstractExecutorInterceptor.java new file mode 100644 index 0000000000..092a82f14b --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/AbstractExecutorInterceptor.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2023-2023 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.transmit.interceptor; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.transmit.wrapper.CallableWrapper; +import com.huaweicloud.sermant.router.transmit.wrapper.RunnableAndCallableWrapper; +import com.huaweicloud.sermant.router.transmit.wrapper.RunnableWrapper; + +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * 线程池拦截器抽象类 + * + * @author provenceee + * @since 2023-06-08 + */ +public abstract class AbstractExecutorInterceptor extends AbstractInterceptor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + private static final String CALLABLE_WRAPPER_CLASS_NAME = CallableWrapper.class.getName(); + + private static final String RUNNABLE_AND_CALLABLE_WRAPPER_CLASS_NAME = RunnableAndCallableWrapper.class.getName(); + + private static final String RUNNABLE_WRAPPER_CLASS_NAME = RunnableWrapper.class.getName(); + + private final boolean cannotTransmit; + + /** + * 构造方法 + * + * @param cannotTransmit 执行方法之前是否需要删除线程变量 + */ + protected AbstractExecutorInterceptor(boolean cannotTransmit) { + this.cannotTransmit = cannotTransmit; + } + + @Override + public ExecuteContext before(ExecuteContext context) { + Object[] arguments = context.getArguments(); + if (arguments == null || arguments.length == 0 || arguments[0] == null) { + return context; + } + RequestHeader requestHeader = ThreadLocalUtils.getRequestHeader(); + RequestData requestData = ThreadLocalUtils.getRequestData(); + if (requestHeader == null && requestData == null) { + return context; + } + Object argument = arguments[0]; + if (argument instanceof RunnableAndCallableWrapper || argument instanceof RunnableWrapper + || argument instanceof CallableWrapper) { + return context; + } + if (argument instanceof Runnable && argument instanceof Callable) { + arguments[0] = getRunnableAndCallableWrapper(argument, requestHeader, requestData); + return context; + } + if (argument instanceof Runnable) { + arguments[0] = getRunnableWrapper(argument, requestHeader, requestData); + return context; + } + if (argument instanceof Callable) { + arguments[0] = getCallableWrapper(argument, requestHeader, requestData); + return context; + } + return context; + } + + private RunnableAndCallableWrapper getRunnableAndCallableWrapper(Object argument, RequestHeader requestHeader, + RequestData requestData) { + log(argument, requestHeader, requestData, RUNNABLE_AND_CALLABLE_WRAPPER_CLASS_NAME); + return new RunnableAndCallableWrapper<>((Runnable) argument, (Callable) argument, requestHeader, requestData, + cannotTransmit); + } + + private RunnableWrapper getRunnableWrapper(Object argument, RequestHeader requestHeader, + RequestData requestData) { + log(argument, requestHeader, requestData, RUNNABLE_WRAPPER_CLASS_NAME); + return new RunnableWrapper<>((Runnable) argument, requestHeader, requestData, cannotTransmit); + } + + private CallableWrapper getCallableWrapper(Object argument, RequestHeader requestHeader, + RequestData requestData) { + log(argument, requestHeader, requestData, CALLABLE_WRAPPER_CLASS_NAME); + return new CallableWrapper<>((Callable) argument, requestHeader, requestData, cannotTransmit); + } + + private void log(Object argument, RequestHeader requestHeader, RequestData requestData, String wrapperClassName) { + LOGGER.log(Level.FINE, "Class name is {0}, hash code is {1}, requestTag is {2}, " + + "requestData is {3}, will be converted to {4}.", + new Object[]{argument.getClass().getName(), Integer.toHexString(argument.hashCode()), + requestHeader, requestData, wrapperClassName}); + } + + @Override + public ExecuteContext after(ExecuteContext context) { + return context; + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptor.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptor.java new file mode 100644 index 0000000000..0de2129500 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptor.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023-2023 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.transmit.interceptor; + +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +/** + * 拦截Executor + * + * @author provenceee + * @since 2023-04-21 + */ +public class ExecutorInterceptor extends AbstractExecutorInterceptor { + /** + * 构造方法 + */ + public ExecutorInterceptor() { + super(!PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledThreadPool()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptor.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptor.java new file mode 100644 index 0000000000..4e0b4749ae --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptor.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023-2023 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.transmit.interceptor; + +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +/** + * 拦截ScheduledExecutorService + * + * @author provenceee + * @since 2023-06-07 + */ +public class ScheduledExecutorServiceInterceptor extends AbstractExecutorInterceptor { + /** + * 构造方法 + */ + public ScheduledExecutorServiceInterceptor() { + super(!PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledScheduler()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/AbstractThreadWrapper.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/AbstractThreadWrapper.java new file mode 100644 index 0000000000..47fe420d50 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/AbstractThreadWrapper.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; + +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Callable/Runnable包装抽象类 + * + * @param 泛型 + * @author provenceee + * @since 2023-06-08 + */ +public abstract class AbstractThreadWrapper { + private static final Logger LOGGER = LoggerFactory.getLogger(); + + private final Runnable runnable; + + private final Callable callable; + + private final RequestHeader requestHeader; + + private final RequestData requestData; + + private final boolean cannotTransmit; + + /** + * 构造方法 + * + * @param runnable runnable + * @param callable callable + * @param requestHeader 请求标记 + * @param requestData 请求数据 + * @param cannotTransmit 执行方法之前是否需要删除线程变量 + */ + public AbstractThreadWrapper(Runnable runnable, Callable callable, RequestHeader requestHeader, + RequestData requestData, boolean cannotTransmit) { + this.runnable = runnable; + this.callable = callable; + if (cannotTransmit) { + this.requestHeader = null; + this.requestData = null; + } else { + this.requestHeader = requestHeader; + this.requestData = requestData; + } + this.cannotTransmit = cannotTransmit; + } + + /** + * run方法 + */ + public void run() { + try { + before(runnable); + runnable.run(); + } finally { + after(); + } + } + + /** + * call + * + * @return callable调用结果 + * @throws Exception 异常 + */ + public T call() throws Exception { + try { + before(callable); + return callable.call(); + } finally { + after(); + } + } + + private void before(Object obj) { + if (cannotTransmit) { + // 当开启普通线程透传,不开启线程池透传时,需要在执行方法之前,删除由InheritableThreadLocal透传的数据 + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + if (requestHeader != null) { + ThreadLocalUtils.setRequestHeader(requestHeader); + } + if (requestData != null) { + ThreadLocalUtils.setRequestData(requestData); + } + LOGGER.log(Level.FINE, "Current thread is {0}, class name is {1}, hash code is {2}, requestTag is {3}, " + + "requestData is {4}, will be executed.", + new Object[]{Thread.currentThread().getName(), obj.getClass().getName(), + Integer.toHexString(obj.hashCode()), requestHeader, requestData}); + } + + private void after() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapper.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapper.java new file mode 100644 index 0000000000..a7167c3324 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapper.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; + +import java.util.concurrent.Callable; + +/** + * Callable包装类 + * + * @param 泛型 + * @author provenceee + * @since 2023-04-21 + */ +public class CallableWrapper extends AbstractThreadWrapper implements Callable { + /** + * 构造方法 + * + * @param callable callable + * @param requestHeader 请求标记 + * @param requestData 请求数据 + * @param cannotTransmit 执行方法之前是否需要删除线程变量 + */ + public CallableWrapper(Callable callable, RequestHeader requestHeader, RequestData requestData, + boolean cannotTransmit) { + super(null, callable, requestHeader, requestData, cannotTransmit); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapper.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapper.java new file mode 100644 index 0000000000..056d6ded8d --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapper.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; + +import java.util.concurrent.Callable; + +/** + * Runnable&Callable包装类,例如reactor.core.scheduler.WorkerTask + * + * @param 泛型 + * @author provenceee + * @since 2023-04-21 + */ +public class RunnableAndCallableWrapper extends AbstractThreadWrapper implements Runnable, Callable { + /** + * 构造方法 + * + * @param runnable runnable + * @param callable callable + * @param requestHeader 请求标记 + * @param requestData 请求数据 + * @param cannotTransmit 执行方法之前是否需要删除线程变量 + */ + public RunnableAndCallableWrapper(Runnable runnable, Callable callable, RequestHeader requestHeader, + RequestData requestData, boolean cannotTransmit) { + super(runnable, callable, requestHeader, requestData, cannotTransmit); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapper.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapper.java new file mode 100644 index 0000000000..14ee015776 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapper.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; + +/** + * Runnable包装类 + * + * @param 泛型 + * @author provenceee + * @since 2023-04-21 + */ +public class RunnableWrapper extends AbstractThreadWrapper implements Runnable { + /** + * 构造方法 + * + * @param runnable runnable + * @param requestHeader 请求标记 + * @param requestData 请求数据 + * @param cannotTransmit 执行方法之前是否需要删除线程变量 + */ + public RunnableWrapper(Runnable runnable, RequestHeader requestHeader, RequestData requestData, + boolean cannotTransmit) { + super(runnable, null, requestHeader, requestData, cannotTransmit); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..250f5b71a2 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -0,0 +1,2 @@ +com.huaweicloud.sermant.router.transmit.declarer.ExecutorDeclarer +com.huaweicloud.sermant.router.transmit.declarer.ScheduledExecutorServiceDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/BaseTest.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/BaseTest.java new file mode 100644 index 0000000000..7da4d93430 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/BaseTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2023-2023 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.transmit; + +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +/** + * 测试基类 + * + * @author provenceee + * @since 2023-06-08 + */ +public abstract class BaseTest { + protected static MockedStatic mockPluginConfigManager; + + @BeforeClass + public static void before() { + mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockPluginConfigManager.close(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/RunnableAndCallable.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/RunnableAndCallable.java new file mode 100644 index 0000000000..c5fa2f553c --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/RunnableAndCallable.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023-2023 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.transmit; + +import java.util.concurrent.Callable; + +/** + * @author provenceee + * @since 2023-06-13 + */ +public class RunnableAndCallable implements Runnable, Callable { + @Override + public void run() { + } + + @Override + public Object call() { + return new Object(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptorTest.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptorTest.java new file mode 100644 index 0000000000..eefe266355 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ExecutorInterceptorTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2023-2023 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.transmit.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.transmit.BaseTest; +import com.huaweicloud.sermant.router.transmit.RunnableAndCallable; +import com.huaweicloud.sermant.router.transmit.wrapper.CallableWrapper; +import com.huaweicloud.sermant.router.transmit.wrapper.RunnableAndCallableWrapper; +import com.huaweicloud.sermant.router.transmit.wrapper.RunnableWrapper; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.concurrent.Callable; + +/** + * 测试ExecutorInterceptor + * + * @author provenceee + * @since 2023-05-26 + */ +public class ExecutorInterceptorTest extends BaseTest { + private final ExecutorInterceptor interceptor; + + private final ExecuteContext context; + + private final Object[] arguments; + + public ExecutorInterceptorTest() { + arguments = new Object[1]; + interceptor = new ExecutorInterceptor(); + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Test + public void testBefore() { + // 测试null + interceptor.before(context); + Assert.assertNull(context.getArguments()[0]); + + // 测试没有路由数据 + Runnable runnable = () -> { + }; + arguments[0] = runnable; + interceptor.before(context); + Assert.assertEquals(runnable, context.getArguments()[0]); + + // 存入路由数据 + ThreadLocalUtils.setRequestHeader(new RequestHeader(Collections.singletonMap("foo", Collections.singletonList("bar")))); + + // 测试已经包装过了 + RunnableWrapper runnableWrapper = new RunnableWrapper<>(null, null, null, false); + arguments[0] = runnableWrapper; + interceptor.before(context); + Assert.assertEquals(runnableWrapper, context.getArguments()[0]); + + // 包装RunnableAndCallable + RunnableAndCallable runnableAndCallable = new RunnableAndCallable(); + arguments[0] = runnableAndCallable; + interceptor.before(context); + Assert.assertTrue(context.getArguments()[0] instanceof RunnableAndCallableWrapper); + + // 包装Runnable + Runnable runnable1 = () -> { + }; + arguments[0] = runnable1; + interceptor.before(context); + Assert.assertTrue(context.getArguments()[0] instanceof RunnableWrapper); + + // 包装Callable + Callable callable = () -> null; + arguments[0] = callable; + interceptor.before(context); + Assert.assertTrue(context.getArguments()[0] instanceof CallableWrapper); + } + + @After + public void clear() { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestHeader(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptorTest.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptorTest.java new file mode 100644 index 0000000000..eedd86b1be --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/interceptor/ScheduledExecutorServiceInterceptorTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2023-2023 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.transmit.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.transmit.BaseTest; +import com.huaweicloud.sermant.router.transmit.RunnableAndCallable; +import com.huaweicloud.sermant.router.transmit.wrapper.CallableWrapper; +import com.huaweicloud.sermant.router.transmit.wrapper.RunnableAndCallableWrapper; +import com.huaweicloud.sermant.router.transmit.wrapper.RunnableWrapper; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.concurrent.Callable; + +/** + * 测试ScheduledExecutorService + * + * @author provenceee + * @since 2023-06-13 + */ +public class ScheduledExecutorServiceInterceptorTest extends BaseTest { + private final ScheduledExecutorServiceInterceptor interceptor; + + private final ExecuteContext context; + + private final Object[] arguments; + + public ScheduledExecutorServiceInterceptorTest() { + arguments = new Object[1]; + interceptor = new ScheduledExecutorServiceInterceptor(); + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Test + public void testBefore() { + // 测试null + interceptor.before(context); + Assert.assertNull(context.getArguments()[0]); + + // 测试没有路由数据 + Runnable runnable = () -> { + }; + arguments[0] = runnable; + interceptor.before(context); + Assert.assertEquals(runnable, context.getArguments()[0]); + + // 存入路由数据 + ThreadLocalUtils.setRequestHeader(new RequestHeader(Collections.singletonMap("foo", + Collections.singletonList("bar")))); + + // 测试已经包装过了 + RunnableWrapper runnableWrapper = new RunnableWrapper<>(null, null, null, false); + arguments[0] = runnableWrapper; + interceptor.before(context); + Assert.assertEquals(runnableWrapper, context.getArguments()[0]); + + // 包装RunnableAndCallable + RunnableAndCallable runnableAndCallable = new RunnableAndCallable(); + arguments[0] = runnableAndCallable; + interceptor.before(context); + Assert.assertTrue(context.getArguments()[0] instanceof RunnableAndCallableWrapper); + + // 包装Runnable + Runnable runnable1 = () -> { + }; + arguments[0] = runnable1; + interceptor.before(context); + Assert.assertTrue(context.getArguments()[0] instanceof RunnableWrapper); + + // 包装Callable + Callable callable = () -> null; + arguments[0] = callable; + interceptor.before(context); + Assert.assertTrue(context.getArguments()[0] instanceof CallableWrapper); + } + + @After + public void clear() { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestHeader(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapperTest.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapperTest.java new file mode 100644 index 0000000000..2ddfc3fc4d --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/CallableWrapperTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.core.utils.ReflectUtils; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.transmit.BaseTest; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 测试CallableWrapper + * + * @author provenceee + * @since 2023-05-27 + */ +public class CallableWrapperTest extends BaseTest { + @Test + public void testCanTransmit() throws Exception { + Object obj = new Object(); + CallableWrapper wrapper = new CallableWrapper<>(() -> { + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + return obj; + }, new RequestHeader(null), new RequestData(null, null, null), false); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + + Assert.assertEquals(obj, wrapper.call()); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } + + @Test + public void testCannotTransmit() throws Exception { + // 初始条件 + ThreadLocalUtils.setRequestHeader(new RequestHeader(null)); + ThreadLocalUtils.setRequestData(new RequestData(null, null, null)); + + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + + Object obj = new Object(); + CallableWrapper wrapper = new CallableWrapper<>(() -> { + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + return obj; + }, new RequestHeader(null), new RequestData(null, null, null), true); + + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestData").orElse(null)); + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestHeader").orElse(null)); + + Assert.assertEquals(obj, wrapper.call()); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapperTest.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapperTest.java new file mode 100644 index 0000000000..ab3ad126a9 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableAndCallableWrapperTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.core.utils.ReflectUtils; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.transmit.BaseTest; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 测试RunnableAndCallableWrapper + * + * @author provenceee + * @since 2023-05-27 + */ +public class RunnableAndCallableWrapperTest extends BaseTest { + @Test + public void testRunCanTransmit() { + RunnableAndCallableWrapper wrapper = new RunnableAndCallableWrapper<>(() -> { + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + }, null, new RequestHeader(null), new RequestData(null, null, null), false); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + + wrapper.run(); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } + + @Test + public void testRunCannotTransmit() { + // 初始条件 + ThreadLocalUtils.setRequestHeader(new RequestHeader(null)); + ThreadLocalUtils.setRequestData(new RequestData(null, null, null)); + + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + + RunnableWrapper wrapper = new RunnableWrapper<>(() -> { + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + }, new RequestHeader(null), new RequestData(null, null, null), true); + + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestData").orElse(null)); + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestHeader").orElse(null)); + + wrapper.run(); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } + + @Test + public void testCallCanTransmit() throws Exception { + Object obj = new Object(); + RunnableAndCallableWrapper wrapper = new RunnableAndCallableWrapper<>(null, () -> { + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + return obj; + }, new RequestHeader(null), new RequestData(null, null, null), false); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + + Assert.assertEquals(obj, wrapper.call()); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } + + @Test + public void testCallCannotTransmit() throws Exception { + // 初始条件 + ThreadLocalUtils.setRequestHeader(new RequestHeader(null)); + ThreadLocalUtils.setRequestData(new RequestData(null, null, null)); + + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + + Object obj = new Object(); + CallableWrapper wrapper = new CallableWrapper<>(() -> { + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + return obj; + }, new RequestHeader(null), new RequestData(null, null, null), true); + + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestData").orElse(null)); + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestHeader").orElse(null)); + + Assert.assertEquals(obj, wrapper.call()); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapperTest.java b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapperTest.java new file mode 100644 index 0000000000..07609ca2a4 --- /dev/null +++ b/sermant-plugins/sermant-router/router-transmit-plugin/src/test/java/com/huaweicloud/sermant/router/transmit/wrapper/RunnableWrapperTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023-2023 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.transmit.wrapper; + +import com.huaweicloud.sermant.core.utils.ReflectUtils; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.transmit.BaseTest; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 测试RunnableWrapper + * + * @author provenceee + * @since 2023-05-27 + */ +public class RunnableWrapperTest extends BaseTest { + @Test + public void testCanTransmit() { + RunnableWrapper wrapper = new RunnableWrapper<>(() -> { + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + }, new RequestHeader(null), new RequestData(null, null, null), false); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + + wrapper.run(); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } + + @Test + public void testCannotTransmit() { + // 初始条件 + ThreadLocalUtils.setRequestHeader(new RequestHeader(null)); + ThreadLocalUtils.setRequestData(new RequestData(null, null, null)); + + Assert.assertNotNull(ThreadLocalUtils.getRequestData()); + Assert.assertNotNull(ThreadLocalUtils.getRequestHeader()); + + RunnableWrapper wrapper = new RunnableWrapper<>(() -> { + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + }, new RequestHeader(null), new RequestData(null, null, null), true); + + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestData").orElse(null)); + Assert.assertNull(ReflectUtils.getFieldValue(wrapper, "requestHeader").orElse(null)); + + wrapper.run(); + + Assert.assertNull(ThreadLocalUtils.getRequestData()); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/pom.xml b/sermant-plugins/sermant-router/spring-router-plugin/pom.xml index 727a18cc02..92bcdeb64d 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/pom.xml +++ b/sermant-plugins/sermant-router/spring-router-plugin/pom.xml @@ -26,6 +26,7 @@ 2.7.5 4.3 4.1.5 + 0.9.0.RELEASE @@ -52,6 +53,12 @@ ${spring.version} provided + + org.springframework + spring-webflux + ${spring.version} + provided + org.springframework spring-webmvc @@ -64,6 +71,12 @@ ${spring.version} provided + + io.projectreactor.netty + reactor-netty + ${reactor.version} + provided + io.github.openfeign feign-core diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ControllerDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ControllerDeclarer.java deleted file mode 100644 index 1a33ce9de7..0000000000 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ControllerDeclarer.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2022-2022 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; -import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; - -/** - * 增强Controller的RequestMapping方法 - * - * @author provenceee - * @since 2022-10-29 - */ -public class ControllerDeclarer extends AbstractDeclarer { - private static final String CONTROLLER_ANNOTATION = "org.springframework.stereotype.Controller"; - - private static final String REST_CONTROLLER_ANNOTATION = "org.springframework.web.bind.annotation.RestController"; - - private static final String INTERCEPT_CLASS - = "com.huaweicloud.sermant.router.spring.interceptor.ControllerInterceptor"; - - private static final String REQUEST_MAPPING_NAME = "org.springframework.web.bind.annotation.RequestMapping"; - - private static final String POST_MAPPING_NAME = "org.springframework.web.bind.annotation.PostMapping"; - - private static final String GET_MAPPING_NAME = "org.springframework.web.bind.annotation.GetMapping"; - - private static final String DELETE_MAPPING_NAME = "org.springframework.web.bind.annotation.DeleteMapping"; - - private static final String PATCH_MAPPING_NAME = "org.springframework.web.bind.annotation.PatchMapping"; - - private static final String PUT_MAPPING_NAME = "org.springframework.web.bind.annotation.PutMapping"; - - /** - * 构造方法 - */ - public ControllerDeclarer() { - super(null, INTERCEPT_CLASS, null); - } - - @Override - public ClassMatcher getClassMatcher() { - return ClassMatcher.isAnnotatedWith(CONTROLLER_ANNOTATION) - .or(ClassMatcher.isAnnotatedWith(REST_CONTROLLER_ANNOTATION)); - } - - @Override - public MethodMatcher getMethodMatcher() { - return MethodMatcher.isAnnotatedWith(REQUEST_MAPPING_NAME) - .or(MethodMatcher.isAnnotatedWith(POST_MAPPING_NAME)) - .or(MethodMatcher.isAnnotatedWith(GET_MAPPING_NAME)) - .or(MethodMatcher.isAnnotatedWith(DELETE_MAPPING_NAME)) - .or(MethodMatcher.isAnnotatedWith(PATCH_MAPPING_NAME)) - .or(MethodMatcher.isAnnotatedWith(PUT_MAPPING_NAME)); - } -} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerHandleDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerHandleDeclarer.java new file mode 100644 index 0000000000..b26f20c8c9 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerHandleDeclarer.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023-2023 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; + +/** + * HttpServerHandle拦截点,只引入spring-boot-starter-webflux进行响应式编程时,需要在后置方法移除线程变量 + *

spring cloud Greenwich.RELEASE+ + * + * @author provenceee + * @since 2023-06-09 + */ +public class HttpServerHandleDeclarer extends AbstractDeclarer { + private static final String[] ENHANCE_CLASS + = {"reactor.netty.http.server.HttpServerHandle", "reactor.netty.http.server.HttpServer$HttpServerHandle"}; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.HttpServerHandleInterceptor"; + + private static final String METHOD_NAME = "onStateChange"; + + /** + * 构造方法 + */ + public HttpServerHandleDeclarer() { + super(null, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameContains(ENHANCE_CLASS); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerOperationsDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerOperationsDeclarer.java new file mode 100644 index 0000000000..a4876b78a1 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HttpServerOperationsDeclarer.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023-2023 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; + +/** + * HttpServerOperations拦截点,只引入spring-boot-starter-webflux进行响应式编程时,需要在后置方法移除线程变量 + *

spring cloud Finchley.x + * + * @author provenceee + * @since 2023-06-09 + */ +public class HttpServerOperationsDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS = "reactor.ipc.netty.http.server.HttpServerOperations"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.HttpServerOperationsInterceptor"; + + private static final String METHOD_NAME = "onHandlerStart"; + + /** + * 构造方法 + */ + public HttpServerOperationsDeclarer() { + super(null, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HystrixActionDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HystrixActionDeclarer.java index b989ecdc22..71aab4cce3 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HystrixActionDeclarer.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/HystrixActionDeclarer.java @@ -18,6 +18,8 @@ import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import net.bytebuddy.matcher.ElementMatchers; @@ -51,4 +53,9 @@ public ClassMatcher getClassMatcher() { public MethodMatcher getMethodMatcher() { return MethodMatcher.isConstructor().and(ElementMatchers.takesArguments(ARGS_LENGTH)); } + + @Override + public boolean isEnabled() { + return !PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledThreadPool(); + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerClientFilterDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerClientFilterDeclarer.java index 540e55af52..75a0ec6bc3 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerClientFilterDeclarer.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerClientFilterDeclarer.java @@ -25,8 +25,7 @@ * @since 2022-07-12 */ public class LoadBalancerClientFilterDeclarer extends AbstractDeclarer { - private static final String[] ENHANCE_CLASS = {"org.springframework.cloud.gateway.filter.LoadBalancerClientFilter", - "org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter"}; + private static final String ENHANCE_CLASS = "org.springframework.cloud.gateway.filter.LoadBalancerClientFilter"; private static final String INTERCEPT_CLASS = "com.huaweicloud.sermant.router.spring.interceptor.LoadBalancerClientFilterInterceptor"; @@ -42,6 +41,6 @@ public LoadBalancerClientFilterDeclarer() { @Override public ClassMatcher getClassMatcher() { - return ClassMatcher.nameContains(ENHANCE_CLASS); + return ClassMatcher.nameEquals(ENHANCE_CLASS); } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerDeclarer.java new file mode 100644 index 0000000000..32cff00bfd --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/LoadBalancerDeclarer.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023-2023 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; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +/** + * spring cloud loadbalancer拦截点 + * + * @author provenceee + * @since 2023-04-21 + */ +public class LoadBalancerDeclarer extends AbstractDeclarer { + private static final String[] ENHANCE_CLASS = {"org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer", + "org.springframework.cloud.loadbalancer.core.RandomLoadBalancer"}; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.LoadBalancerInterceptor"; + + private static final String METHOD_NAME = "getInstanceResponse"; + + /** + * 构造方法 + */ + public LoadBalancerDeclarer() { + super(null, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameContains(ENHANCE_CLASS); + } + + @Override + public boolean isEnabled() { + return PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledThreadPool(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveLoadBalancerClientFilterDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveLoadBalancerClientFilterDeclarer.java new file mode 100644 index 0000000000..b271ab438d --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveLoadBalancerClientFilterDeclarer.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023-2023 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; + +/** + * spring cloud gateway ReactiveLoadBalancerClientFilter增强类,获取请求数据 + * + * @author provenceee + * @since 2023-06-07 + */ +public class ReactiveLoadBalancerClientFilterDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS + = "org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.ReactiveLoadBalancerClientFilterInterceptor"; + + private static final String METHOD_NAME = "filter"; + + /** + * 构造方法 + */ + public ReactiveLoadBalancerClientFilterDeclarer() { + super(null, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveTypeHandlerDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveTypeHandlerDeclarer.java new file mode 100644 index 0000000000..4f7ca23da5 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ReactiveTypeHandlerDeclarer.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023-2023 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; + +/** + * ReactiveTypeHandler拦截点,同时引入spring-boot-starter-web、spring-boot-starter-webflux进行响应式编程时,需要在后置方法移除线程变量 + *

spring cloud Finchley.RELEASE+ + * + * @author provenceee + * @since 2023-06-09 + */ +public class ReactiveTypeHandlerDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS + = "org.springframework.web.servlet.mvc.method.annotation.ReactiveTypeHandler"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.ReactiveTypeHandlerInterceptor"; + + private static final String METHOD_NAME = "handleValue"; + + /** + * 构造方法 + */ + public ReactiveTypeHandlerDeclarer() { + super(null, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ServiceInstanceListSupplierDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ServiceInstanceListSupplierDeclarer.java index 1abd8c0c2d..14c409c91c 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ServiceInstanceListSupplierDeclarer.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/ServiceInstanceListSupplierDeclarer.java @@ -17,6 +17,8 @@ package com.huaweicloud.sermant.router.spring.declarer; import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; /** * CachingServiceInstanceListSupplier/DiscoveryClientServiceInstanceListSupplier增强类,筛选下游实例 @@ -45,4 +47,9 @@ public ServiceInstanceListSupplierDeclarer() { public ClassMatcher getClassMatcher() { return ClassMatcher.nameContains(ENHANCE_CLASS); } + + @Override + public boolean isEnabled() { + return !PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledThreadPool(); + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/WebClientBuilderDeclarer.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/WebClientBuilderDeclarer.java new file mode 100644 index 0000000000..dd3e1343a4 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/declarer/WebClientBuilderDeclarer.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023-2023 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.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +/** + * webclient拦截点,springboot 2.0.0.RELEASE+,注入请求过滤器 + * + * @author provenceee + * @since 2023-06-12 + */ +public class WebClientBuilderDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS = "org.springframework.web.reactive.function.client.WebClient$Builder"; + + private static final String INTERCEPT_CLASS + = "com.huaweicloud.sermant.router.spring.interceptor.WebClientBuilderInterceptor"; + + private static final String METHOD_NAME = "build"; + + /** + * 构造方法 + */ + public WebClientBuilderDeclarer() { + super(ENHANCE_CLASS, INTERCEPT_CLASS, METHOD_NAME); + } + + @Override + public boolean isEnabled() { + return PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledThreadPool(); + } +} \ 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/AbstractHandlerMappingInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptor.java index 7d055d1bc3..fadcfadade 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptor.java @@ -24,7 +24,6 @@ import com.huaweicloud.sermant.router.spring.service.SpringConfigService; import org.springframework.http.HttpHeaders; -import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.server.ServerWebExchange; import java.util.HashMap; @@ -39,6 +38,9 @@ * @since 2022-10-10 */ public class AbstractHandlerMappingInterceptor extends AbstractInterceptor { + private static final String EXCEPT_CLASS_NAME + = "org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping"; + private final SpringConfigService configService; /** @@ -86,6 +88,6 @@ private Map> getHeader(HttpHeaders headers) { private boolean shouldHandle(ExecuteContext context) { Object[] arguments = context.getArguments(); return arguments.length > 0 && arguments[0] instanceof ServerWebExchange - && context.getObject() instanceof RequestMappingHandlerMapping; + && EXCEPT_CLASS_NAME.equals(context.getObject().getClass().getName()); } } \ 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/EurekaHttpClientInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptor.java index 5bb2aadbf1..1d26017d0f 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 @@ -19,8 +19,11 @@ import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; import com.huaweicloud.sermant.router.spring.cache.AppCache; +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; import com.huaweicloud.sermant.router.spring.utils.SpringRouterUtils; import com.netflix.appinfo.InstanceInfo; @@ -34,11 +37,14 @@ public class EurekaHttpClientInterceptor extends AbstractInterceptor { private final RouterConfig routerConfig; + private final SpringConfigService configService; + /** * 构造方法 */ public EurekaHttpClientInterceptor() { routerConfig = PluginConfigManager.getPluginConfig(RouterConfig.class); + configService = ServiceManager.getService(SpringConfigService.class); } @Override @@ -54,6 +60,7 @@ 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/FeignClientInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java index a8e7d45a81..a632e3d8c5 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptor.java @@ -18,7 +18,9 @@ import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.utils.StringUtils; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.CollectionUtils; @@ -157,6 +159,9 @@ private Map> decodeTags(Map> headers) } private boolean canLoadHystrix() { + if (PluginConfigManager.getPluginConfig(TransmitConfig.class).isEnabledThreadPool()) { + return false; + } try { Class.forName(HystrixRequestContext.class.getCanonicalName()); } catch (NoClassDefFoundError | ClassNotFoundException error) { diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerHandleInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerHandleInterceptor.java new file mode 100644 index 0000000000..7b9bc81744 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerHandleInterceptor.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023-2023 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.router.common.utils.ThreadLocalUtils; + +import reactor.netty.ConnectionObserver.State; + +/** + * 拦截HttpServerHandle,只引入spring-boot-starter-webflux进行响应式编程时,需要在后置方法移除线程变量 + *

spring cloud Greenwich.RELEASE+ + * + * @author provenceee + * @since 2023-06-09 + */ +public class HttpServerHandleInterceptor extends AbstractInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + if (shouldHandle(context)) { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestHeader(); + } + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) { + if (shouldHandle(context)) { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestHeader(); + } + return context; + } + + private boolean shouldHandle(ExecuteContext context) { + Object argument = context.getArguments()[1]; + if (argument instanceof State) { + State state = (State) argument; + return state == State.DISCONNECTING; + } + return false; + } +} \ 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/ControllerInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerOperationsInterceptor.java similarity index 75% rename from sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ControllerInterceptor.java rename to sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerOperationsInterceptor.java index 79c1b7b5b8..f4f1fd630e 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ControllerInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/HttpServerOperationsInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (C) 2023-2023 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. @@ -21,12 +21,13 @@ import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; /** - * 增强Controller的RequestMapping方法 + * 拦截HttpServerOperations,只引入spring-boot-starter-webflux进行响应式编程时,需要在后置方法移除线程变量 + *

spring cloud Finchley.x * * @author provenceee - * @since 2022-10-29 + * @since 2023-06-12 */ -public class ControllerInterceptor extends AbstractInterceptor { +public class HttpServerOperationsInterceptor extends AbstractInterceptor { @Override public ExecuteContext before(ExecuteContext context) { return context; @@ -34,12 +35,14 @@ public ExecuteContext before(ExecuteContext context) { @Override public ExecuteContext after(ExecuteContext context) { + ThreadLocalUtils.removeRequestData(); ThreadLocalUtils.removeRequestHeader(); return context; } @Override public ExecuteContext onThrow(ExecuteContext context) { + ThreadLocalUtils.removeRequestData(); ThreadLocalUtils.removeRequestHeader(); return context; } diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptor.java index 4932474e78..84722ce16d 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptor.java @@ -25,11 +25,6 @@ import org.springframework.http.HttpRequest; import org.springframework.web.server.ServerWebExchange; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - /** * spring cloud gateway LoadBalancerClientFilter增强类,获取请求数据 * @@ -45,28 +40,22 @@ public ExecuteContext before(ExecuteContext context) { HttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); String path = request.getURI().getPath(); - ThreadLocalUtils.setRequestData(new RequestData(getHeader(headers), path, request.getMethod().name())); + ThreadLocalUtils.setRequestData(new RequestData(headers, path, request.getMethod().name())); } return context; } @Override public ExecuteContext after(ExecuteContext context) { + ThreadLocalUtils.removeRequestHeader(); ThreadLocalUtils.removeRequestData(); return context; } @Override public ExecuteContext onThrow(ExecuteContext context) { + ThreadLocalUtils.removeRequestHeader(); ThreadLocalUtils.removeRequestData(); return context; } - - private Map> getHeader(HttpHeaders headers) { - Map> map = new HashMap<>(); - for (Entry> entry : headers.entrySet()) { - map.put(entry.getKey(), entry.getValue()); - } - return map; - } } \ 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/LoadBalancerInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerInterceptor.java new file mode 100644 index 0000000000..f4fccd6c43 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerInterceptor.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023-2023 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.config.PluginConfigManager; +import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.core.utils.StringUtils; +import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.utils.CollectionUtils; +import com.huaweicloud.sermant.router.common.utils.ReflectUtils; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; + +import java.util.List; +import java.util.Optional; + +/** + * spring cloud loadbalancer拦截点 + * + * @author provenceee + * @since 2023-04-21 + */ +public class LoadBalancerInterceptor extends AbstractInterceptor { + private final LoadBalancerService loadBalancerService; + + private final RouterConfig routerConfig; + + /** + * 构造方法 + */ + public LoadBalancerInterceptor() { + loadBalancerService = ServiceManager.getService(LoadBalancerService.class); + routerConfig = PluginConfigManager.getPluginConfig(RouterConfig.class); + } + + @Override + public ExecuteContext before(ExecuteContext context) { + Object object = context.getObject(); + String serviceId = getServiceId(object).orElse(null); + if (StringUtils.isBlank(serviceId)) { + return context; + } + Object[] arguments = context.getArguments(); + List instances = (List) arguments[0]; + if (CollectionUtils.isEmpty(instances)) { + return context; + } + RequestData requestData = ThreadLocalUtils.getRequestData(); + if (requestData == null) { + arguments[0] = loadBalancerService.getZoneInstances(serviceId, instances, + routerConfig.isEnabledSpringZoneRouter()); + return context; + } + List list = loadBalancerService.getTargetInstances(serviceId, instances, requestData.getPath(), + requestData.getHeader()); + arguments[0] = loadBalancerService.getZoneInstances(serviceId, list, routerConfig.isEnabledSpringZoneRouter()); + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + return context; + } + + private Optional getServiceId(Object object) { + return ReflectUtils.getFieldValue(object, "serviceId").map(obj -> (String) obj); + } +} \ 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/ReactiveLoadBalancerClientFilterInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ReactiveLoadBalancerClientFilterInterceptor.java new file mode 100644 index 0000000000..f83dd90aa9 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ReactiveLoadBalancerClientFilterInterceptor.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2023-2023 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.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; +import com.huaweicloud.sermant.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; + +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; + +/** + * spring cloud gateway ReactiveLoadBalancerClientFilter增强类,获取请求数据 + * + * @author provenceee + * @since 2023-06-07 + */ +public class ReactiveLoadBalancerClientFilterInterceptor extends AbstractInterceptor { + private final TransmitConfig config; + + /** + * 构造方法 + */ + public ReactiveLoadBalancerClientFilterInterceptor() { + this.config = PluginConfigManager.getPluginConfig(TransmitConfig.class); + } + + @Override + public ExecuteContext before(ExecuteContext context) { + if (context.getArguments()[0] instanceof ServerWebExchange) { + ServerHttpRequest request = ((ServerWebExchange) context.getArguments()[0]).getRequest(); + String path = request.getURI().getPath(); + ThreadLocalUtils.setRequestData(new RequestData(request.getHeaders(), path, request.getMethod().name())); + } + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + // ReactiveLoadBalancerClientFilter为响应式编程,开启线程池透传时不能在after方法中删除,否则会导致线程变量无法透传到负载均衡线程中 + // 会在HttpServerHandleInterceptor、ReactiveTypeHandlerInterceptor中删除 + if (!config.isEnabledThreadPool()) { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + 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/ReactiveTypeHandlerInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ReactiveTypeHandlerInterceptor.java new file mode 100644 index 0000000000..e0e1f042d7 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ReactiveTypeHandlerInterceptor.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2023-2023 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.router.common.utils.ThreadLocalUtils; + +/** + * 拦截ReactiveTypeHandler,同时引入spring-boot-starter-web、spring-boot-starter-webflux进行响应式编程时,需要在后置方法移除线程变量 + *

spring cloud Finchley.RELEASE+ + * + * @author provenceee + * @since 2023-06-09 + */ +public class ReactiveTypeHandlerInterceptor extends AbstractInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestHeader(); + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) { + ThreadLocalUtils.removeRequestData(); + ThreadLocalUtils.removeRequestHeader(); + 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/RouterExchangeFilterFunction.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouterExchangeFilterFunction.java new file mode 100644 index 0000000000..c3b71e6398 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/RouterExchangeFilterFunction.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023-2023 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.router.common.request.RequestData; +import com.huaweicloud.sermant.router.common.request.RequestHeader; +import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; + +import reactor.core.publisher.Mono; + +import org.springframework.http.HttpHeaders; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ClientRequest.Builder; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.ExchangeFunction; + +/** + * webclient拦截器,获取&注入请求头 + * + * @author provenceee + * @since 2023-06-12 + */ +public class RouterExchangeFilterFunction implements ExchangeFilterFunction { + @Override + public Mono filter(ClientRequest request, ExchangeFunction exchangeFunction) { + HttpHeaders readOnlyHttpHeaders = request.headers(); + RequestHeader requestHeader = ThreadLocalUtils.getRequestHeader(); + if (requestHeader == null) { + ThreadLocalUtils.setRequestData(new RequestData(readOnlyHttpHeaders, request.url().getPath(), + request.method().name())); + return exchangeFunction.exchange(request); + } + Builder newRequestBuilder = ClientRequest.from(request); + requestHeader.getHeader().forEach((key, value) -> newRequestBuilder.header(key, value.toArray(new String[0]))); + ClientRequest newRequest = newRequestBuilder.build(); + ThreadLocalUtils.setRequestData(new RequestData(newRequest.headers(), newRequest.url().getPath(), + newRequest.method().name())); + return exchangeFunction.exchange(newRequest); + } +} \ 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/WebClientBuilderInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/WebClientBuilderInterceptor.java new file mode 100644 index 0000000000..5ea3cf2f21 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/WebClientBuilderInterceptor.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023-2023 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.utils.ClassUtils; +import com.huaweicloud.sermant.core.utils.ReflectUtils; + +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient.Builder; + +import java.util.List; +import java.util.Optional; + +/** + * 注入请求过滤器 + * + * @author provenceee + * @since 2023-06-12 + */ +public class WebClientBuilderInterceptor extends AbstractInterceptor { + private static final String EXCHANGE_FILTER_FUNCTION_CLASS_NAME + = "com.huaweicloud.sermant.router.spring.interceptor.RouterExchangeFilterFunction"; + + private static volatile boolean init; + + @Override + public ExecuteContext before(ExecuteContext context) { + if (!(context.getObject() instanceof Builder)) { + return context; + } + init(); + Builder builder = (Builder) context.getObject(); + Optional filters = ReflectUtils.getFieldValue(builder, "filters"); + if (filters.isPresent()) { + List list = (List) filters.get(); + for (ExchangeFilterFunction filterFunction : list) { + if (filterFunction instanceof RouterExchangeFilterFunction) { + // 已经注入重试的不再注入 + return context; + } + } + + // 存在过滤器时,注入到第一个 + list.add(0, new RouterExchangeFilterFunction()); + return context; + } + builder.filter(new RouterExchangeFilterFunction()); + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + return context; + } + + private void init() { + if (!init) { + synchronized (WebClientBuilderInterceptor.class) { + if (!init) { + ClassUtils.defineClass(EXCHANGE_FILTER_FUNCTION_CLASS_NAME, getClass().getClassLoader()); + init = true; + } + } + } + } +} \ No newline at end of file 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 c7d4e5b179..64c3040364 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 @@ -1,7 +1,6 @@ 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.ControllerDeclarer com.huaweicloud.sermant.router.spring.declarer.DiscoveryManagerDeclarer com.huaweicloud.sermant.router.spring.declarer.EurekaHttpClientDeclarer com.huaweicloud.sermant.router.spring.declarer.FeignClientDeclarer @@ -17,4 +16,10 @@ com.huaweicloud.sermant.router.spring.declarer.HttpClient4xDeclarer com.huaweicloud.sermant.router.spring.declarer.HttpUrlConnectionConnectDeclarer com.huaweicloud.sermant.router.spring.declarer.RestTemplateDeclarer com.huaweicloud.sermant.router.spring.declarer.SpringBootLoadClassDeclarer -com.huaweicloud.sermant.router.spring.declarer.HttpAsyncClient4xDeclarer \ No newline at end of file +com.huaweicloud.sermant.router.spring.declarer.HttpAsyncClient4xDeclarer +com.huaweicloud.sermant.router.spring.declarer.LoadBalancerDeclarer +com.huaweicloud.sermant.router.spring.declarer.ReactiveLoadBalancerClientFilterDeclarer +com.huaweicloud.sermant.router.spring.declarer.HttpServerHandleDeclarer +com.huaweicloud.sermant.router.spring.declarer.ReactiveTypeHandlerDeclarer +com.huaweicloud.sermant.router.spring.declarer.WebClientBuilderDeclarer +com.huaweicloud.sermant.router.spring.declarer.HttpServerOperationsDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/BaseTransmitConfigTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/BaseTransmitConfigTest.java new file mode 100644 index 0000000000..f3f7ec430e --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/BaseTransmitConfigTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023-2023 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; + +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +/** + * mock TransmitConfig测试基类 + * + * @author provenceee + * @since 2023-06-08 + */ +public abstract class BaseTransmitConfigTest { + protected static MockedStatic mockPluginConfigManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void initTransmitConfig() { + mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void closeMock() { + mockPluginConfigManager.close(); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptorTest.java index 3f71f79461..4e6ca272c6 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/AbstractHandlerMappingInterceptorTest.java @@ -20,6 +20,7 @@ import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.spring.BaseTransmitConfigTest; import com.huaweicloud.sermant.router.spring.service.SpringConfigService; import org.junit.AfterClass; @@ -45,7 +46,7 @@ * @author provenceee * @since 2022-10-10 */ -public class AbstractHandlerMappingInterceptorTest { +public class AbstractHandlerMappingInterceptorTest extends BaseTransmitConfigTest { private final AbstractHandlerMappingInterceptor interceptor; private final ExecuteContext context; diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java index cbfb98e1bb..a36221b78a 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java @@ -20,6 +20,7 @@ import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; @@ -73,6 +74,8 @@ public static void before() { mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(RouterConfig.class)) .thenReturn(new RouterConfig()); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); } /** diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java index 4b2da1cb86..e860aae6d6 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java @@ -20,6 +20,7 @@ import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.spring.BaseTransmitConfigTest; import org.junit.Assert; import org.junit.Before; @@ -38,7 +39,7 @@ * @author provenceee * @since 2022-09-08 */ -public class ClientHttpRequestInterceptorTest { +public class ClientHttpRequestInterceptorTest extends BaseTransmitConfigTest { private final ClientHttpRequestInterceptor interceptor; private final ExecuteContext context; diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ControllerInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ControllerInterceptorTest.java deleted file mode 100644 index 26fecd8636..0000000000 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ControllerInterceptorTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2022-2022 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.router.common.request.RequestHeader; -import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.Collections; - -/** - * 测试ControllerInterceptor - * - * @author provenceee - * @since 2022-10-29 - */ -public class ControllerInterceptorTest { - private final ControllerInterceptor interceptor; - - private final ExecuteContext context; - - public ControllerInterceptorTest() { - interceptor = new ControllerInterceptor(); - context = ExecuteContext.forMemberMethod(new Object(), null, null, null, null); - } - - /** - * 重置测试数据 - */ - @Before - public void clear() { - ThreadLocalUtils.removeRequestHeader(); - ThreadLocalUtils.removeRequestData(); - } - - /** - * 测试after方法,验证是否释放线程变量 - */ - @Test - public void testAfter() { - ThreadLocalUtils.setRequestHeader(new RequestHeader(Collections.emptyMap())); - - // 测试after方法,验证是否释放线程变量 - interceptor.after(context); - Assert.assertNull(ThreadLocalUtils.getRequestHeader()); - } - - /** - * 测试onThrow方法,验证是否释放线程变量 - */ - @Test - public void testOnThrow() { - ThreadLocalUtils.setRequestHeader(new RequestHeader(Collections.emptyMap())); - - // 测试onThrow方法,验证是否释放线程变量 - interceptor.onThrow(context); - Assert.assertNull(ThreadLocalUtils.getRequestHeader()); - } -} \ No newline at end of file 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 da86a3d9e5..a2eab07005 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 @@ -17,14 +17,21 @@ package com.huaweicloud.sermant.router.spring.interceptor; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; import com.huaweicloud.sermant.router.spring.cache.AppCache; +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.Builder; +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -44,6 +51,28 @@ public class EurekaHttpClientInterceptorTest { private final ExecuteContext context; + private static TestSpringConfigService configService; + + private static MockedStatic mockServiceManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void before() { + configService = new TestSpringConfigService(); + mockServiceManager = Mockito.mockStatic(ServiceManager.class); + mockServiceManager.when(() -> ServiceManager.getService(SpringConfigService.class)).thenReturn(configService); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockServiceManager.close(); + } + public EurekaHttpClientInterceptorTest() throws IllegalAccessException, NoSuchFieldException { interceptor = new EurekaHttpClientInterceptor(); routerConfig = new RouterConfig(); @@ -82,4 +111,15 @@ public void testBefore() { 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()); + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java index 5fc2692216..8d91be975e 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java @@ -19,6 +19,7 @@ import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; @@ -73,6 +74,8 @@ public static void before() { mockStatic = Mockito.mockStatic(PluginConfigManager.class); RouterConfig config = new RouterConfig(); mockStatic.when(() -> PluginConfigManager.getPluginConfig(Mockito.any())).thenReturn(config); + mockStatic.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); } @AfterClass diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java index bd2383b677..5d66754f01 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java @@ -20,12 +20,14 @@ import com.huaweicloud.sermant.router.common.request.RequestHeader; import com.huaweicloud.sermant.router.common.utils.ReflectUtils; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.spring.BaseTransmitConfigTest; import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault; import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableDefault; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import java.util.Collections; @@ -40,7 +42,7 @@ * @author provenceee * @since 2022-09-08 */ -public class HystrixActionInterceptorTest { +public class HystrixActionInterceptorTest extends BaseTransmitConfigTest { private final HystrixActionInterceptor interceptor; private final ExecuteContext context; @@ -52,6 +54,15 @@ public HystrixActionInterceptorTest() { context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); } + /** + * 重置测试数据 + */ + @Before + public void clear() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + /** * 测试before方法 */ diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java index 7fbe5bd19b..b4969138b4 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java @@ -19,6 +19,7 @@ import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; +import com.huaweicloud.sermant.router.spring.BaseTransmitConfigTest; import org.junit.Assert; import org.junit.Before; @@ -37,7 +38,7 @@ * @author provenceee * @since 2022-09-08 */ -public class LoadBalancerClientFilterInterceptorTest { +public class LoadBalancerClientFilterInterceptorTest extends BaseTransmitConfigTest { private final LoadBalancerClientFilterInterceptor interceptor; private final ExecuteContext context; diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/NopInstanceFilterInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/NopInstanceFilterInterceptorTest.java index e4c41d14bb..fc41f62ba9 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/NopInstanceFilterInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/NopInstanceFilterInterceptorTest.java @@ -20,6 +20,7 @@ import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; @@ -69,6 +70,8 @@ public static void before() { mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(RouterConfig.class)) .thenReturn(config); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); } /** diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java index 8460428b51..9798f006ea 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java @@ -20,6 +20,7 @@ import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.service.ServiceManager; import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.config.TransmitConfig; import com.huaweicloud.sermant.router.common.request.RequestData; import com.huaweicloud.sermant.router.common.utils.ThreadLocalUtils; import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; @@ -70,6 +71,8 @@ public static void before() { mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(RouterConfig.class)) .thenReturn(new RouterConfig()); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(TransmitConfig.class)) + .thenReturn(new TransmitConfig()); } /**