From ed3b2ee3d18a88e68cab3c962c9de86b1b1b0b55 Mon Sep 17 00:00:00 2001 From: liangl Date: Sat, 25 Apr 2020 21:53:33 +0800 Subject: [PATCH 1/8] [1416] fix sentinel-apache-dubbo-adapter full gc problem --- .../dubbo/BaseSentinelDubboFilter.java | 48 ++-- .../sentinel/adapter/dubbo/DubboUtils.java | 9 +- .../dubbo/SentinelDubboConsumerFilter.java | 7 +- .../dubbo/SentinelDubboProviderFilter.java | 6 +- .../com/alibaba/csp/sentinel/BaseTest.java | 65 ++--- .../alibaba/csp/sentinel/DubboTestUtil.java | 80 ++++++ .../adapter/dubbo/DubboUtilsTest.java | 28 +- .../SentinelDubboConsumerFilterTest.java | 249 ++++++++++-------- .../SentinelDubboProviderFilterTest.java | 49 ++-- 9 files changed, 332 insertions(+), 209 deletions(-) create mode 100644 sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/DubboTestUtil.java diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java index bc2101ffb2..08a0fbdcf5 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java @@ -22,7 +22,11 @@ import com.alibaba.csp.sentinel.context.ContextUtil; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.rpc.*; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.ListenableFilter; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; /** * Base Class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}. @@ -38,43 +42,47 @@ public BaseSentinelDubboFilter() { static class SentinelDubboListener implements Listener { public void onResponse(Result appResponse, Invoker invoker, Invocation invocation) { - onSuccess(appResponse, invoker); + onSuccess(appResponse, invoker, invocation); } //for compatible dubbo 2.7.5 rename onResponse to onMessage public void onMessage(Result appResponse, Invoker invoker, Invocation invocation) { - onSuccess(appResponse, invoker); + onSuccess(appResponse, invoker, invocation); } - private void onSuccess(Result appResponse, Invoker invoker) { + private void onSuccess(Result appResponse, Invoker invoker, Invocation invocation) { if (DubboConfig.getDubboBizExceptionTraceEnabled()) { - traceAndExit(appResponse.getException(), invoker.getUrl()); + traceAndExit(appResponse.getException(), invoker, invocation); } else { - traceAndExit(null, invoker.getUrl()); + traceAndExit(null, invoker, invocation); } } @Override public void onError(Throwable t, Invoker invoker, Invocation invocation) { - traceAndExit(t, invoker.getUrl()); + traceAndExit(t, invoker, invocation); } } - static void traceAndExit(Throwable throwable, URL url) { - Entry interfaceEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY); - Entry methodEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY); - if (methodEntry != null) { - Tracer.traceEntry(throwable, methodEntry); - methodEntry.exit(); - RpcContext.getContext().remove(DubboUtils.DUBBO_METHOD_ENTRY_KEY); - } - if (interfaceEntry != null) { - Tracer.traceEntry(throwable, interfaceEntry); - interfaceEntry.exit(); - RpcContext.getContext().remove(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY); + static void traceAndExit(Throwable throwable, Invoker invoker, Invocation invocation) { + String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); + Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); + if (entries != null) { + Entry interfaceEntry = entries[0]; + Entry methodEntry = entries[1]; + if (methodEntry != null) { + Tracer.traceEntry(throwable, methodEntry); + methodEntry.exit(); + } + if (interfaceEntry != null) { + Tracer.traceEntry(throwable, interfaceEntry); + interfaceEntry.exit(); + } + RpcContext.getContext().remove(methodResourceName); } - if (CommonConstants.PROVIDER_SIDE.equals(url.getParameter(CommonConstants.SIDE_KEY))) { + URL url = invoker.getUrl(); + if (CommonConstants.PROVIDER_SIDE.equals(invoker.getUrl().getParameter(CommonConstants.SIDE_KEY))) { ContextUtil.exit(); } } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java index d2c325fafd..c2a720d29f 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java @@ -26,8 +26,6 @@ public final class DubboUtils { public static final String SENTINEL_DUBBO_APPLICATION_KEY = "dubboApplication"; - public static final String DUBBO_METHOD_ENTRY_KEY = "dubboMethodEntry"; - public static final String DUBBO_INTERFACE_ENTRY_KEY = "dubboInterfaceEntry"; public static String getApplication(Invocation invocation, String defaultValue) { if (invocation == null || invocation.getAttachments() == null) { @@ -69,6 +67,13 @@ public static String getResourceName(Invoker invoker, Invocation invocation, return getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled()); } } + + + public static String getInterfaceName(Invoker invoker) { + return DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey() + : invoker.getInterface().getName(); + } + private DubboUtils() { } } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java index ffa9fba9cf..28574013fe 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java @@ -59,21 +59,18 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept RpcContext rpcContext = RpcContext.getContext(); try { String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); - String interfaceResourceName = DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey() - : invoker.getInterface().getName(); + String interfaceResourceName = DubboUtils.getInterfaceName(invoker); InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation); if (InvokeMode.SYNC == invokeMode) { interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); - rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry); methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); } else { // should generate the AsyncEntry when the invoke model in future or async interfaceEntry = SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); - rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry); methodEntry = SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments()); } - rpcContext.set(DubboUtils.DUBBO_METHOD_ENTRY_KEY, methodEntry); + rpcContext.set(methodResourceName, new Entry[]{interfaceEntry, methodEntry}); return invoker.invoke(invocation); } catch (BlockException e) { return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java index c919978694..07e3a718da 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java @@ -61,15 +61,13 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept Entry methodEntry = null; try { String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); - String interfaceResourceName = DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey() - : invoker.getInterface().getName(); + String interfaceResourceName = DubboUtils.getInterfaceName(invoker); // Only need to create entrance context at provider side, as context will take effect // at entrance of invocation chain only (for inbound traffic). ContextUtil.enter(methodResourceName, application); interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN); - rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry); methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments()); - rpcContext.set(DubboUtils.DUBBO_METHOD_ENTRY_KEY, methodEntry); + rpcContext.set(methodResourceName, new Entry[]{interfaceEntry, methodEntry}); return invoker.invoke(invocation); } catch (BlockException e) { return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e); diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/BaseTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/BaseTest.java index 7793a6567e..46948c5715 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/BaseTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/BaseTest.java @@ -16,25 +16,19 @@ package com.alibaba.csp.sentinel; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; -import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; +import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DefaultDubboFallback; +import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; import com.alibaba.csp.sentinel.config.SentinelConfig; import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.rpc.Invocation; -import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcContext; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - /** * Base test class, provide common methods for subClass * The package is same as CtSph, to call CtSph.resetChainMap() method for test @@ -42,46 +36,41 @@ * Note: Only for test. DO NOT USE IN PRODUCTION! * * @author cdfive + * @author lianglin */ public class BaseTest { - protected Invoker invoker; - protected Invocation invocation; - - public void constructInvokerAndInvocation() { - invoker = mock(Invoker.class); - URL url = URL.valueOf("dubbo://127.0.0.1:2181") - .addParameter(CommonConstants.VERSION_KEY, "1.0.0") - .addParameter(CommonConstants.GROUP_KEY, "grp1") - .addParameter(CommonConstants.INTERFACE_KEY, DemoService.class.getName()); - when(invoker.getUrl()).thenReturn(url); - when(invoker.getInterface()).thenReturn(DemoService.class); - - invocation = mock(Invocation.class); - Method method = DemoService.class.getMethods()[0]; - when(invocation.getMethodName()).thenReturn(method.getName()); - when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); - - } - /** * Clean up resources for context, clusterNodeMap, processorSlotChainMap */ - protected static void cleanUpAll() { + public void cleanUpAll() { try { - RpcContext.removeContext(); - ClusterBuilderSlot.getClusterNodeMap().clear(); - CtSph.resetChainMap(); - Method method = ContextUtil.class.getDeclaredMethod("resetContextMap"); - method.setAccessible(true); - method.invoke(null, null); - ContextUtil.exit(); - SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "true"); - FlowRuleManager.loadRules(new ArrayList<>()); - DegradeRuleManager.loadRules(new ArrayList<>()); + clearDubboContext(); + cleanUpCstContext(); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } + + private void cleanUpCstContext() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + ClusterBuilderSlot.getClusterNodeMap().clear(); + CtSph.resetChainMap(); + Method method = ContextUtil.class.getDeclaredMethod("resetContextMap"); + method.setAccessible(true); + method.invoke(null, null); + ContextUtil.exit(); + FlowRuleManager.loadRules(new ArrayList<>()); + DegradeRuleManager.loadRules(new ArrayList<>()); + } + + private void clearDubboContext() { + SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "false"); + SentinelConfig.setConfig(DubboConfig.DUBBO_PROVIDER_PREFIX, ""); + SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, ""); + SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); + DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); + RpcContext.removeContext(); + + } } \ No newline at end of file diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/DubboTestUtil.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/DubboTestUtil.java new file mode 100644 index 0000000000..326f216b24 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/DubboTestUtil.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * 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.alibaba.csp.sentinel; + +import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; + +import java.lang.reflect.Method; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author lianglin + */ +public class DubboTestUtil { + + + public static Class DEFAULT_TEST_SERVICE = DemoService.class; + public static Method DEFAULT_TEST_METHOD_ONE = DEFAULT_TEST_SERVICE.getMethods()[0]; + public static Method DEFAULT_TEST_METHOD_TWO = DEFAULT_TEST_SERVICE.getMethods()[1]; + + public static Invoker getMockInvoker(URL url, Class cls) { + Invoker invoker = mock(Invoker.class); + when(invoker.getUrl()).thenReturn(url); + when(invoker.getInterface()).thenReturn(cls); + return invoker; + } + + public static Invoker getDefaultMockInvoker() { + return getMockInvoker(getDefaultTestURL(), DEFAULT_TEST_SERVICE); + } + + public static Invocation getMockInvocation(Method method) { + Invocation invocation = mock(Invocation.class); + when(invocation.getMethodName()).thenReturn(method.getName()); + when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); + return invocation; + } + + public static Invocation getDefaultMockInvocationOne() { + Invocation invocation = mock(Invocation.class); + when(invocation.getMethodName()).thenReturn(DEFAULT_TEST_METHOD_ONE.getName()); + when(invocation.getParameterTypes()).thenReturn(DEFAULT_TEST_METHOD_ONE.getParameterTypes()); + return invocation; + } + + public static Invocation getDefaultMockInvocationTwo() { + Invocation invocation = mock(Invocation.class); + when(invocation.getMethodName()).thenReturn(DEFAULT_TEST_METHOD_TWO.getName()); + when(invocation.getParameterTypes()).thenReturn(DEFAULT_TEST_METHOD_TWO.getParameterTypes()); + return invocation; + } + + public static URL getDefaultTestURL() { + URL url = URL.valueOf("dubbo://127.0.0.1:2181") + .addParameter(CommonConstants.VERSION_KEY, "1.0.0") + .addParameter(CommonConstants.GROUP_KEY, "grp1") + .addParameter(CommonConstants.INTERFACE_KEY, DEFAULT_TEST_SERVICE.getName()); + return url; + } + + +} diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java index ece46fde3d..4b4eadeaf1 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java @@ -29,11 +29,10 @@ import java.lang.reflect.Method; import java.util.HashMap; +import static com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; /** * @author cdfive @@ -45,7 +44,7 @@ public void setUp() { SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "true"); SentinelConfig.setConfig(DubboConfig.DUBBO_PROVIDER_PREFIX, ""); SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, ""); - SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); + SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); } @@ -54,7 +53,7 @@ public void tearDown() { SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "false"); SentinelConfig.setConfig(DubboConfig.DUBBO_PROVIDER_PREFIX, ""); SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, ""); - SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); + SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); } @@ -146,4 +145,23 @@ public void testGetResourceNameWithPrefix() throws NoSuchMethodException { assertEquals("my:dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); } + + @Test + public void testGetInterfaceName() { + + URL url = URL.valueOf("dubbo://127.0.0.1:2181") + .addParameter(CommonConstants.VERSION_KEY, "1.0.0") + .addParameter(CommonConstants.GROUP_KEY, "grp1") + .addParameter(CommonConstants.INTERFACE_KEY, DemoService.class.getName()); + Invoker invoker = mock(Invoker.class); + when(invoker.getUrl()).thenReturn(url); + when(invoker.getInterface()).thenReturn(DemoService.class); + + SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); + assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", DubboUtils.getInterfaceName(invoker)); + + SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "true"); + assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:1.0.0:grp1", DubboUtils.getInterfaceName(invoker)); + + } } \ No newline at end of file diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java index ea69ab8bdb..e0a79819d8 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java @@ -16,13 +16,12 @@ package com.alibaba.csp.sentinel.adapter.dubbo; import com.alibaba.csp.sentinel.BaseTest; +import com.alibaba.csp.sentinel.DubboTestUtil; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; -import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DefaultDubboFallback; import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallback; import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; -import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; import com.alibaba.csp.sentinel.context.Context; import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.node.ClusterNode; @@ -46,7 +45,6 @@ import org.junit.Before; import org.junit.Test; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -56,105 +54,83 @@ import static com.alibaba.csp.sentinel.slots.block.RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO; import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; /** * @author cdfive + * @author lianglin */ public class SentinelDubboConsumerFilterTest extends BaseTest { - private SentinelDubboConsumerFilter filter = new SentinelDubboConsumerFilter(); + private SentinelDubboConsumerFilter consumerFilter = new SentinelDubboConsumerFilter(); + @Before public void setUp() { cleanUpAll(); initFallback(); - constructInvokerAndInvocation(); } @After - public void cleanUp() { - cleanUpAll(); - DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); + public void destroy() { + cleanUpAll(); } - public void initFlowRule(String resource) { - FlowRule flowRule = new FlowRule(resource); - flowRule.setCount(1); - flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); - List flowRules = new ArrayList<>(); - flowRules.add(flowRule); - FlowRuleManager.loadRules(flowRules); - } - - public void initDegradeRule(String resource) { - DegradeRule degradeRule = new DegradeRule(resource) - .setCount(0.5) - .setGrade(DEGRADE_GRADE_EXCEPTION_RATIO); - List degradeRules = new ArrayList<>(); - degradeRules.add(degradeRule); - degradeRule.setTimeWindow(1); - DegradeRuleManager.loadRules(degradeRules); - } - - - public void initFallback() { - DubboFallbackRegistry.setConsumerFallback(new DubboFallback() { - @Override - public Result handle(Invoker invoker, Invocation invocation, BlockException ex) { - boolean async = RpcUtils.isAsync(invoker.getUrl(), invocation); - Result fallbackResult = null; - fallbackResult = AsyncRpcResult.newDefaultAsyncResult("fallback", invocation); - return fallbackResult; - } - }); - } @Test public void testInterfaceLevelFollowControlAsync() throws InterruptedException { + + Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); + Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); + when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); - initFlowRule(invoker.getUrl().getColonSeparatedKey()); - Result result1 = responseBack(requestGo(false, invocation)); + initFlowRule(DubboUtils.getInterfaceName(invoker)); + + Result result1 = invokeDubboRpc(false, invoker, invocation); assertEquals("normal", result1.getValue()); + // should fallback because the qps > 1 - Result result2 = responseBack(requestGo(false, invocation)); + Result result2 = invokeDubboRpc(false, invoker, invocation); assertEquals("fallback", result2.getValue()); + // sleeping 1000 ms to reset qps Thread.sleep(1000); - Result result3 = responseBack(requestGo(false, invocation)); + Result result3 = invokeDubboRpc(false, invoker, invocation); assertEquals("normal", result3.getValue()); - verifyInvocationStructureForCallFinish(); + verifyInvocationStructureForCallFinish(invoker, invocation); } @Test public void testDegradeAsync() throws InterruptedException { + + Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); + Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); + when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); + initDegradeRule(DubboUtils.getInterfaceName(invoker)); - initDegradeRule(invoker.getUrl().getColonSeparatedKey()); - Result result = requestGo(false, invocation); + Result result = requestGo(false, invoker, invocation); verifyInvocationStructureForAsyncCall(invoker, invocation); - responseBack(result); + responseBack(result, invoker, invocation); + verifyInvocationStructureForCallFinish(invoker, invocation); assertEquals("normal", result.getValue()); + + // inc the clusterNode's exception to trigger the fallback for (int i = 0; i < 5; i++) { - responseBack(requestGo(true, invocation)); - verifyInvocationStructureForCallFinish(); + invokeDubboRpc(true, invoker, invocation); + verifyInvocationStructureForCallFinish(invoker, invocation); } - Result result2 = responseBack(requestGo(false, invocation)); + + Result result2 = invokeDubboRpc(false, invoker, invocation); assertEquals("fallback", result2.getValue()); + // sleeping 1000 ms to reset exception Thread.sleep(1000); - - Result result3 = responseBack(requestGo(false, invocation)); + Result result3 = invokeDubboRpc(false, invoker, invocation); assertEquals("normal", result3.getValue()); Context context = ContextUtil.getContext(); @@ -164,22 +140,28 @@ public void testDegradeAsync() throws InterruptedException { @Test public void testDegradeSync() throws InterruptedException { - initDegradeRule(invoker.getUrl().getColonSeparatedKey()); - Result result = requestGo(false, invocation); + Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); + Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); + initDegradeRule(DubboUtils.getInterfaceName(invoker)); + + Result result = requestGo(false, invoker, invocation); verifyInvocationStructure(invoker, invocation); - responseBack(result); + responseBack(result, invoker, invocation); + verifyInvocationStructureForCallFinish(invoker, invocation); assertEquals("normal", result.getValue()); + // inc the clusterNode's exception to trigger the fallback for (int i = 0; i < 5; i++) { - responseBack(requestGo(true, invocation)); - verifyInvocationStructureForCallFinish(); + invokeDubboRpc(true, invoker, invocation); + verifyInvocationStructureForCallFinish(invoker, invocation); } - Result result2 = responseBack(requestGo(false, invocation)); + + Result result2 = invokeDubboRpc(false, invoker, invocation); assertEquals("fallback", result2.getValue()); + // sleeping 1000 ms to reset exception Thread.sleep(1000); - - Result result3 = responseBack(requestGo(false, invocation)); + Result result3 = invokeDubboRpc(false, invoker, invocation); assertEquals("normal", result3.getValue()); Context context = ContextUtil.getContext(); @@ -189,54 +171,36 @@ public void testDegradeSync() throws InterruptedException { @Test public void testMethodFlowControlAsync() { + + Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); + Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); + when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); initFlowRule(DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix())); - responseBack(requestGo(false, invocation)); - - responseBack(requestGo(false, invocation)); + invokeDubboRpc(false, invoker, invocation); + invokeDubboRpc(false, invoker, invocation); - Invocation invocation2 = mock(Invocation.class); - Method method = DemoService.class.getMethods()[1]; - when(invocation2.getMethodName()).thenReturn(method.getName()); - when(invocation2.getParameterTypes()).thenReturn(method.getParameterTypes()); - Result result2 = responseBack(requestGo(false, invocation2)); - verifyInvocationStructureForCallFinish(); + Invocation invocation2 = DubboTestUtil.getDefaultMockInvocationTwo(); + Result result2 = invokeDubboRpc(false, invoker, invocation2); + verifyInvocationStructureForCallFinish(invoker, invocation2); assertEquals("normal", result2.getValue()); // the method of invocation should be blocked - Result fallback = requestGo(false, invocation); - assertNotNull(RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY)); - assertNull(RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY)); - responseBack(fallback); + Result fallback = invokeDubboRpc(false, invoker, invocation); assertEquals("fallback", fallback.getValue()); - verifyInvocationStructureForCallFinish(); - + verifyInvocationStructureForCallFinish(invoker, invocation); - } - - public Result requestGo(boolean exception, Invocation currentInvocation) { - AsyncRpcResult result = null; - - if (exception) { - result = AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), currentInvocation); - } else { - result = AsyncRpcResult.newDefaultAsyncResult("normal", currentInvocation); - } - when(invoker.invoke(currentInvocation)).thenReturn(result); - return filter.invoke(invoker, currentInvocation); - } - public Result responseBack(Result result) { - filter.listener().onMessage(result, invoker, invocation); - return result; } @Test public void testInvokeAsync() throws InterruptedException { - when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); + Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); + Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); + when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); final Result result = mock(Result.class); when(result.hasException()).thenReturn(false); when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> { @@ -244,7 +208,7 @@ public void testInvokeAsync() throws InterruptedException { return result; }); - filter.invoke(invoker, invocation); + consumerFilter.invoke(invoker, invocation); verify(invoker).invoke(invocation); Context context = ContextUtil.getContext(); @@ -254,6 +218,9 @@ public void testInvokeAsync() throws InterruptedException { @Test public void testInvokeSync() { + Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); + Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); + final Result result = mock(Result.class); when(result.hasException()).thenReturn(false); when(result.getException()).thenReturn(new Exception()); @@ -262,14 +229,16 @@ public void testInvokeSync() { return result; }); - filter.invoke(invoker, invocation); + consumerFilter.invoke(invoker, invocation); verify(invoker).invoke(invocation); - filter.listener().onMessage(result, invoker, invocation); + consumerFilter.listener().onMessage(result, invoker, invocation); Context context = ContextUtil.getContext(); assertNull(context); } + + /** * Simply verify invocation structure in memory: * EntranceNode(defaultContextName) @@ -282,7 +251,7 @@ private void verifyInvocationStructure(Invoker invoker, Invocation invocation) { // As not call ContextUtil.enter(resourceName, application) in SentinelDubboConsumerFilter, use default context // In actual project, a consumer is usually also a provider, the context will be created by SentinelDubboProviderFilter // If consumer is on the top of Dubbo RPC invocation chain, use default context - String resourceName = DubboUtils.getResourceName(invoker, invocation, true); + String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); assertEquals("", context.getOrigin()); @@ -335,7 +304,7 @@ private void verifyInvocationStructureForAsyncCall(Invoker invoker, Invocation i // As not call ContextUtil.enter(resourceName, application) in SentinelDubboConsumerFilter, use default context // In actual project, a consumer is usually also a provider, the context will be created by SentinelDubboProviderFilter // If consumer is on the top of Dubbo RPC invocation chain, use default context - String resourceName = DubboUtils.getResourceName(invoker, invocation, true); + String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); assertEquals("", context.getOrigin()); @@ -347,9 +316,9 @@ private void verifyInvocationStructureForAsyncCall(Invoker invoker, Invocation i // As SphU.entry(interfaceName, EntryType.OUT); Set childList = entranceNode.getChildList(); assertEquals(2, childList.size()); - DefaultNode interfaceNode = getNode(invoker.getUrl().getColonSeparatedKey(), entranceNode); + DefaultNode interfaceNode = getNode(DubboUtils.getInterfaceName(invoker), entranceNode); ResourceWrapper interfaceResource = interfaceNode.getId(); - assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName()); + assertEquals(DubboUtils.getInterfaceName(invoker), interfaceResource.getName()); assertSame(EntryType.OUT, interfaceResource.getEntryType()); // As SphU.entry(resourceName, EntryType.OUT); @@ -379,17 +348,16 @@ private void verifyInvocationStructureForAsyncCall(Invoker invoker, Invocation i } - private void verifyInvocationStructureForCallFinish() { + private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) { Context context = ContextUtil.getContext(); assertNull(context); - Entry interfaceEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY); - Entry methodEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY); - assertNull(interfaceEntry); - assertNull(methodEntry); + String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); + Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); + assertNull(entries); } - public DefaultNode getNode(String resourceName, DefaultNode root) { + private DefaultNode getNode(String resourceName, DefaultNode root) { Queue queue = new LinkedList<>(); queue.offer(root); @@ -405,4 +373,59 @@ public DefaultNode getNode(String resourceName, DefaultNode root) { return null; } + + private void initFlowRule(String resource) { + FlowRule flowRule = new FlowRule(resource); + flowRule.setCount(1); + flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); + List flowRules = new ArrayList<>(); + flowRules.add(flowRule); + FlowRuleManager.loadRules(flowRules); + } + + private void initDegradeRule(String resource) { + DegradeRule degradeRule = new DegradeRule(resource) + .setCount(0.5) + .setGrade(DEGRADE_GRADE_EXCEPTION_RATIO); + List degradeRules = new ArrayList<>(); + degradeRules.add(degradeRule); + degradeRule.setTimeWindow(1); + DegradeRuleManager.loadRules(degradeRules); + } + + + private void initFallback() { + DubboFallbackRegistry.setConsumerFallback(new DubboFallback() { + @Override + public Result handle(Invoker invoker, Invocation invocation, BlockException ex) { + boolean async = RpcUtils.isAsync(invoker.getUrl(), invocation); + Result fallbackResult = null; + fallbackResult = AsyncRpcResult.newDefaultAsyncResult("fallback", invocation); + return fallbackResult; + } + }); + } + + private Result invokeDubboRpc(boolean isException, Invoker invoker, Invocation invocation) { + return responseBack(requestGo(isException, invoker, invocation), invoker, invocation); + } + + private Result requestGo(boolean exception, Invoker invoker, Invocation currentInvocation) { + AsyncRpcResult result = null; + + if (exception) { + result = AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), currentInvocation); + } else { + result = AsyncRpcResult.newDefaultAsyncResult("normal", currentInvocation); + } + when(invoker.invoke(currentInvocation)).thenReturn(result); + return consumerFilter.invoke(invoker, currentInvocation); + } + + private Result responseBack(Result result, Invoker invoker, Invocation invocation) { + consumerFilter.listener().onMessage(result, invoker, invocation); + return result; + } + + } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java index ed97800a41..f7a0edae7a 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java @@ -16,8 +16,10 @@ package com.alibaba.csp.sentinel.adapter.dubbo; import com.alibaba.csp.sentinel.BaseTest; +import com.alibaba.csp.sentinel.DubboTestUtil; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; import com.alibaba.csp.sentinel.context.Context; import com.alibaba.csp.sentinel.context.ContextUtil; @@ -35,52 +37,49 @@ import org.junit.Before; import org.junit.Test; -import java.lang.reflect.Method; import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; /** * @author cdfive + * @author lianglin */ public class SentinelDubboProviderFilterTest extends BaseTest { + private SentinelDubboProviderFilter filter = new SentinelDubboProviderFilter(); + @Before public void setUp() { - constructInvokerAndInvocation(); cleanUpAll(); } @After - public void cleanUp() { + public void destroy() { cleanUpAll(); } @Test public void testInvoke() { + final String originApplication = "consumerA"; - URL url = invoker.getUrl() - .addParameter(CommonConstants.SIDE_KEY, CommonConstants.PROVIDER_SIDE); - when(invoker.getUrl()).thenReturn(url); + URL url = DubboTestUtil.getDefaultTestURL(); + url = url.addParameter(CommonConstants.SIDE_KEY, CommonConstants.PROVIDER_SIDE); + Invoker invoker = DubboTestUtil.getMockInvoker(url, DemoService.class); + Invocation invocation = DubboTestUtil.getMockInvocation(DemoService.class.getMethods()[0]); when(invocation.getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, "")) .thenReturn(originApplication); final Result result = mock(Result.class); when(result.hasException()).thenReturn(false); when(result.getException()).thenReturn(new Exception()); + when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> { verifyInvocationStructure(originApplication, invoker, invocation); return result; @@ -96,22 +95,22 @@ public void testInvoke() { /** * Simply verify invocation structure in memory: - * EntranceNode(resourceName) + * EntranceNode(methodResourceName) * --InterfaceNode(interfaceName) - * ----MethodNode(resourceName) + * ----MethodNode(methodResourceName) */ private void verifyInvocationStructure(String originApplication, Invoker invoker, Invocation invocation) { Context context = ContextUtil.getContext(); assertNotNull(context); // As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter - String resourceName = DubboUtils.getResourceName(invoker, invocation, true); - assertEquals(resourceName, context.getName()); + String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); + assertEquals(methodResourceName, context.getName()); assertEquals(originApplication, context.getOrigin()); DefaultNode entranceNode = context.getEntranceNode(); ResourceWrapper entranceResource = entranceNode.getId(); - assertEquals(resourceName, entranceResource.getName()); + assertEquals(methodResourceName, entranceResource.getName()); assertSame(EntryType.IN, entranceResource.getEntryType()); // As SphU.entry(interfaceName, EntryType.IN); @@ -120,7 +119,11 @@ private void verifyInvocationStructure(String originApplication, Invoker invoker DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); ResourceWrapper interfaceResource = interfaceNode.getId(); - assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName()); + if (DubboConfig.getDubboInterfaceGroupAndVersionEnabled()) { + assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName()); + } else { + assertEquals(invoker.getInterface().getName(), interfaceResource.getName()); + } assertSame(EntryType.IN, interfaceResource.getEntryType()); // As SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); @@ -128,7 +131,7 @@ private void verifyInvocationStructure(String originApplication, Invoker invoker assertEquals(1, childList.size()); DefaultNode methodNode = (DefaultNode) childList.iterator().next(); ResourceWrapper methodResource = methodNode.getId(); - assertEquals(resourceName, methodResource.getName()); + assertEquals(methodResourceName, methodResource.getName()); assertSame(EntryType.IN, methodResource.getEntryType()); // Verify curEntry @@ -151,4 +154,6 @@ private void verifyInvocationStructure(String originApplication, Invoker invoker assertEquals(1, interfaceOriginCountMap.size()); assertTrue(interfaceOriginCountMap.containsKey(originApplication)); } + + } From 2dbdd715f5a22b4a73e682d979d96bbc6c2615fc Mon Sep 17 00:00:00 2001 From: liangl Date: Sat, 25 Apr 2020 21:54:21 +0800 Subject: [PATCH 2/8] [1416] fix sentinel-apache-dubbo-adapter full gc problem --- .../csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java index 08a0fbdcf5..4c38a7280d 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java @@ -81,7 +81,6 @@ static void traceAndExit(Throwable throwable, Invoker invoker, Invocation invoca } RpcContext.getContext().remove(methodResourceName); } - URL url = invoker.getUrl(); if (CommonConstants.PROVIDER_SIDE.equals(invoker.getUrl().getParameter(CommonConstants.SIDE_KEY))) { ContextUtil.exit(); } From b854e2d7ae185f8d0efb5a85caee432d436a6757 Mon Sep 17 00:00:00 2001 From: liangl Date: Sat, 25 Apr 2020 23:53:38 +0800 Subject: [PATCH 3/8] [1416] fix test error and update dubbo version --- sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml | 2 +- .../adapter/dubbo/SentinelDubboConsumerFilterTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml b/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml index 44f799db5e..2ece2dbb98 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml @@ -15,7 +15,7 @@ 1.8 1.8 - 2.7.5 + 2.7.6 diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java index e0a79819d8..400e1680a4 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java @@ -264,10 +264,10 @@ private void verifyInvocationStructure(Invoker invoker, Invocation invocation) { // As SphU.entry(interfaceName, EntryType.OUT); Set childList = entranceNode.getChildList(); assertEquals(1, childList.size()); - DefaultNode interfaceNode = getNode(invoker.getUrl().getColonSeparatedKey(), entranceNode); + DefaultNode interfaceNode = getNode(DubboUtils.getInterfaceName(invoker), entranceNode); ResourceWrapper interfaceResource = interfaceNode.getId(); - assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName()); + assertEquals(DubboUtils.getInterfaceName(invoker), interfaceResource.getName()); assertSame(EntryType.OUT, interfaceResource.getEntryType()); // As SphU.entry(resourceName, EntryType.OUT); From 69f51170046bce4d912fed6ddd64c88f9e540c36 Mon Sep 17 00:00:00 2001 From: liangl Date: Sun, 26 Apr 2020 00:01:35 +0800 Subject: [PATCH 4/8] [1416] fix test error and update dubbo version --- sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml b/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml index 2ece2dbb98..44f799db5e 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml @@ -15,7 +15,7 @@ 1.8 1.8 - 2.7.6 + 2.7.5 From f9ad2bd7f6941f55db733af02b2a3df3b70770ff Mon Sep 17 00:00:00 2001 From: liangl Date: Sun, 26 Apr 2020 09:07:09 +0800 Subject: [PATCH 5/8] [1416] BaseSentinelDubboFilter add getMethodName() and getInterfaceName() method --- .../dubbo/BaseSentinelDubboFilter.java | 64 ++++++++++++------- .../dubbo/SentinelDubboConsumerFilter.java | 14 +++- .../dubbo/SentinelDubboProviderFilter.java | 14 +++- .../SentinelDubboConsumerFilterTest.java | 13 ++-- .../SentinelDubboProviderFilterTest.java | 2 +- 5 files changed, 71 insertions(+), 36 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java index 4c38a7280d..10b2a0c7b6 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java @@ -20,7 +20,6 @@ import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; import com.alibaba.csp.sentinel.context.ContextUtil; -import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -39,7 +38,47 @@ public BaseSentinelDubboFilter() { this.listener = new SentinelDubboListener(); } - static class SentinelDubboListener implements Listener { + + private void traceAndExit(Throwable throwable, Invoker invoker, Invocation invocation) { + String methodResourceName = getMethodName(invoker, invocation); + Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); + if (entries != null) { + Entry interfaceEntry = entries[0]; + Entry methodEntry = entries[1]; + if (methodEntry != null) { + Tracer.traceEntry(throwable, methodEntry); + methodEntry.exit(); + } + if (interfaceEntry != null) { + Tracer.traceEntry(throwable, interfaceEntry); + interfaceEntry.exit(); + } + RpcContext.getContext().remove(methodResourceName); + } + if (CommonConstants.PROVIDER_SIDE.equals(invoker.getUrl().getParameter(CommonConstants.SIDE_KEY))) { + ContextUtil.exit(); + } + } + + /** + * Get method name of dubbo rpc + * + * @param invoker + * @param invocation + * @return + */ + abstract String getMethodName(Invoker invoker, Invocation invocation); + + /** + * Get interface name of dubbo rpc + * + * @param invoker + * @return + */ + abstract String getInterfaceName(Invoker invoker); + + + private class SentinelDubboListener implements Listener { public void onResponse(Result appResponse, Invoker invoker, Invocation invocation) { onSuccess(appResponse, invoker, invocation); @@ -64,25 +103,4 @@ public void onError(Throwable t, Invoker invoker, Invocation invocation) { } } - - static void traceAndExit(Throwable throwable, Invoker invoker, Invocation invocation) { - String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); - Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); - if (entries != null) { - Entry interfaceEntry = entries[0]; - Entry methodEntry = entries[1]; - if (methodEntry != null) { - Tracer.traceEntry(throwable, methodEntry); - methodEntry.exit(); - } - if (interfaceEntry != null) { - Tracer.traceEntry(throwable, interfaceEntry); - interfaceEntry.exit(); - } - RpcContext.getContext().remove(methodResourceName); - } - if (CommonConstants.PROVIDER_SIDE.equals(invoker.getUrl().getParameter(CommonConstants.SIDE_KEY))) { - ContextUtil.exit(); - } - } } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java index 28574013fe..6fa8408433 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java @@ -52,14 +52,24 @@ public SentinelDubboConsumerFilter() { RecordLog.info("Sentinel Apache Dubbo consumer filter initialized"); } + @Override + String getMethodName(Invoker invoker, Invocation invocation) { + return DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); + } + + @Override + String getInterfaceName(Invoker invoker) { + return DubboUtils.getInterfaceName(invoker); + } + @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { Entry interfaceEntry = null; Entry methodEntry = null; RpcContext rpcContext = RpcContext.getContext(); try { - String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); - String interfaceResourceName = DubboUtils.getInterfaceName(invoker); + String methodResourceName = getMethodName(invoker, invocation); + String interfaceResourceName = getInterfaceName(invoker); InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation); if (InvokeMode.SYNC == invokeMode) { diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java index 07e3a718da..4b8f64d67f 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java @@ -52,6 +52,16 @@ public SentinelDubboProviderFilter() { RecordLog.info("Sentinel Apache Dubbo provider filter initialized"); } + @Override + String getMethodName(Invoker invoker, Invocation invocation) { + return DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); + } + + @Override + String getInterfaceName(Invoker invoker) { + return DubboUtils.getInterfaceName(invoker); + } + @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { // Get origin caller. @@ -60,8 +70,8 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept Entry interfaceEntry = null; Entry methodEntry = null; try { - String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); - String interfaceResourceName = DubboUtils.getInterfaceName(invoker); + String methodResourceName = getMethodName(invoker, invocation); + String interfaceResourceName = getInterfaceName(invoker); // Only need to create entrance context at provider side, as context will take effect // at entrance of invocation chain only (for inbound traffic). ContextUtil.enter(methodResourceName, application); diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java index 400e1680a4..6fa6aa2f48 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java @@ -19,7 +19,6 @@ import com.alibaba.csp.sentinel.DubboTestUtil; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.EntryType; -import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallback; import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; import com.alibaba.csp.sentinel.context.Context; @@ -66,7 +65,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { private SentinelDubboConsumerFilter consumerFilter = new SentinelDubboConsumerFilter(); - @Before public void setUp() { cleanUpAll(); @@ -75,7 +73,7 @@ public void setUp() { @After public void destroy() { - cleanUpAll(); + cleanUpAll(); } @@ -176,7 +174,7 @@ public void testMethodFlowControlAsync() { Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); - initFlowRule(DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix())); + initFlowRule(consumerFilter.getMethodName(invoker, invocation)); invokeDubboRpc(false, invoker, invocation); invokeDubboRpc(false, invoker, invocation); @@ -238,7 +236,6 @@ public void testInvokeSync() { } - /** * Simply verify invocation structure in memory: * EntranceNode(defaultContextName) @@ -251,7 +248,7 @@ private void verifyInvocationStructure(Invoker invoker, Invocation invocation) { // As not call ContextUtil.enter(resourceName, application) in SentinelDubboConsumerFilter, use default context // In actual project, a consumer is usually also a provider, the context will be created by SentinelDubboProviderFilter // If consumer is on the top of Dubbo RPC invocation chain, use default context - String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); + String resourceName = consumerFilter.getMethodName(invoker, invocation); assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); assertEquals("", context.getOrigin()); @@ -304,7 +301,7 @@ private void verifyInvocationStructureForAsyncCall(Invoker invoker, Invocation i // As not call ContextUtil.enter(resourceName, application) in SentinelDubboConsumerFilter, use default context // In actual project, a consumer is usually also a provider, the context will be created by SentinelDubboProviderFilter // If consumer is on the top of Dubbo RPC invocation chain, use default context - String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); + String resourceName = consumerFilter.getMethodName(invoker, invocation); assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); assertEquals("", context.getOrigin()); @@ -351,7 +348,7 @@ private void verifyInvocationStructureForAsyncCall(Invoker invoker, Invocation i private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) { Context context = ContextUtil.getContext(); assertNull(context); - String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); + String methodResourceName = consumerFilter.getMethodName(invoker, invocation); Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); assertNull(entries); } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java index f7a0edae7a..529d801bb0 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java @@ -104,7 +104,7 @@ private void verifyInvocationStructure(String originApplication, Invoker invoker assertNotNull(context); // As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter - String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); + String methodResourceName = filter.getMethodName(invoker, invocation); assertEquals(methodResourceName, context.getName()); assertEquals(originApplication, context.getOrigin()); From 1f224ff7522644b9d0284c1ef01d51eca63fe17b Mon Sep 17 00:00:00 2001 From: liangl Date: Tue, 28 Apr 2020 09:23:57 +0800 Subject: [PATCH 6/8] [1416] refactor SentinelDubboConsumerFilter and SentinelDubboProviderFilter --- .../dubbo/BaseSentinelDubboFilter.java | 60 +------------- .../dubbo/SentinelDubboConsumerFilter.java | 82 +++++++++++++++---- .../dubbo/SentinelDubboProviderFilter.java | 28 +++++-- 3 files changed, 91 insertions(+), 79 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java index 10b2a0c7b6..d6c964a9ca 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/BaseSentinelDubboFilter.java @@ -16,16 +16,9 @@ package com.alibaba.csp.sentinel.adapter.dubbo; -import com.alibaba.csp.sentinel.Entry; -import com.alibaba.csp.sentinel.Tracer; -import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; -import com.alibaba.csp.sentinel.context.ContextUtil; -import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.ListenableFilter; -import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; /** * Base Class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}. @@ -33,33 +26,9 @@ * @author Zechao Zheng */ -public abstract class BaseSentinelDubboFilter extends ListenableFilter { - public BaseSentinelDubboFilter() { - this.listener = new SentinelDubboListener(); - } +public abstract class BaseSentinelDubboFilter implements Filter { - private void traceAndExit(Throwable throwable, Invoker invoker, Invocation invocation) { - String methodResourceName = getMethodName(invoker, invocation); - Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); - if (entries != null) { - Entry interfaceEntry = entries[0]; - Entry methodEntry = entries[1]; - if (methodEntry != null) { - Tracer.traceEntry(throwable, methodEntry); - methodEntry.exit(); - } - if (interfaceEntry != null) { - Tracer.traceEntry(throwable, interfaceEntry); - interfaceEntry.exit(); - } - RpcContext.getContext().remove(methodResourceName); - } - if (CommonConstants.PROVIDER_SIDE.equals(invoker.getUrl().getParameter(CommonConstants.SIDE_KEY))) { - ContextUtil.exit(); - } - } - /** * Get method name of dubbo rpc * @@ -78,29 +47,4 @@ private void traceAndExit(Throwable throwable, Invoker invoker, Invocation invoc abstract String getInterfaceName(Invoker invoker); - private class SentinelDubboListener implements Listener { - - public void onResponse(Result appResponse, Invoker invoker, Invocation invocation) { - onSuccess(appResponse, invoker, invocation); - } - - //for compatible dubbo 2.7.5 rename onResponse to onMessage - public void onMessage(Result appResponse, Invoker invoker, Invocation invocation) { - onSuccess(appResponse, invoker, invocation); - } - - private void onSuccess(Result appResponse, Invoker invoker, Invocation invocation) { - if (DubboConfig.getDubboBizExceptionTraceEnabled()) { - traceAndExit(appResponse.getException(), invoker, invocation); - } else { - traceAndExit(null, invoker, invocation); - } - } - - @Override - public void onError(Throwable t, Invoker invoker, Invocation invocation) { - traceAndExit(t, invoker, invocation); - } - - } } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java index 6fa8408433..5a95f371a0 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java @@ -19,6 +19,7 @@ import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.ResourceTypeConstants; import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; import com.alibaba.csp.sentinel.log.RecordLog; @@ -28,10 +29,12 @@ import org.apache.dubbo.rpc.InvokeMode; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.support.RpcUtils; +import java.util.Stack; +import java.util.function.BiConsumer; + import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; /** @@ -64,28 +67,77 @@ String getInterfaceName(Invoker invoker) { @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { + InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation); + if (InvokeMode.SYNC == invokeMode) { + return syncInvoke(invoker, invocation); + } else { + return asyncInvoke(invoker, invocation); + } + + } + + private Result syncInvoke(Invoker invoker, Invocation invocation) { Entry interfaceEntry = null; Entry methodEntry = null; - RpcContext rpcContext = RpcContext.getContext(); + String methodResourceName = getMethodName(invoker, invocation); + String interfaceResourceName = getInterfaceName(invoker); try { - String methodResourceName = getMethodName(invoker, invocation); - String interfaceResourceName = getInterfaceName(invoker); - InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation); - - if (InvokeMode.SYNC == invokeMode) { - interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); - methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); - } else { - // should generate the AsyncEntry when the invoke model in future or async - interfaceEntry = SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); - methodEntry = SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments()); + interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); + methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); + Result result = invoker.invoke(invocation); + if (result.hasException()) { + Tracer.traceEntry(result.getException(), interfaceEntry); + Tracer.traceEntry(result.getException(), methodEntry); + } + return result; + } catch (BlockException e) { + return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); + } catch (RpcException e) { + Tracer.traceEntry(e, interfaceEntry); + Tracer.traceEntry(e, methodEntry); + throw e; + } finally { + if (methodEntry != null) { + methodEntry.exit(); + } + if (interfaceEntry != null) { + interfaceEntry.exit(); } - rpcContext.set(methodResourceName, new Entry[]{interfaceEntry, methodEntry}); - return invoker.invoke(invocation); + } + } + + + private Result asyncInvoke(Invoker invoker, Invocation invocation) { + Stack entryStack = new Stack<>(); + String methodResourceName = getMethodName(invoker, invocation); + String interfaceResourceName = getInterfaceName(invoker); + try { + entryStack.push(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT)); + entryStack.push(SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments())); + Result result = invoker.invoke(invocation); + result.whenCompleteWithContext(new BiConsumer() { + @Override + public void accept(Result result, Throwable throwable) { + if (result.hasException()) { + while (entryStack.size() > 0) { + Entry entry = entryStack.pop(); + Tracer.traceEntry(result.getException(), entry); + entry.exit(); + } + } + } + }); + return result; } catch (BlockException e) { + while (entryStack.size() > 0) { + entryStack.pop().exit(); + } return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); } + + } + } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java index 4b8f64d67f..99cf80946b 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java @@ -19,16 +19,17 @@ import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.ResourceTypeConstants; import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.log.RecordLog; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; -import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcException; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; @@ -66,21 +67,36 @@ String getInterfaceName(Invoker invoker) { public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { // Get origin caller. String application = DubboUtils.getApplication(invocation, ""); - RpcContext rpcContext = RpcContext.getContext(); Entry interfaceEntry = null; Entry methodEntry = null; + String methodResourceName = getMethodName(invoker, invocation); + String interfaceResourceName = getInterfaceName(invoker); try { - String methodResourceName = getMethodName(invoker, invocation); - String interfaceResourceName = getInterfaceName(invoker); // Only need to create entrance context at provider side, as context will take effect // at entrance of invocation chain only (for inbound traffic). ContextUtil.enter(methodResourceName, application); interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN); methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments()); - rpcContext.set(methodResourceName, new Entry[]{interfaceEntry, methodEntry}); - return invoker.invoke(invocation); + Result result = invoker.invoke(invocation); + if (result.hasException()) { + Tracer.traceEntry(result.getException(), interfaceEntry); + Tracer.traceEntry(result.getException(), methodEntry); + } + return result; } catch (BlockException e) { return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e); + } catch (RpcException e) { + Tracer.traceEntry(e, interfaceEntry); + Tracer.traceEntry(e, methodEntry); + throw e; + } finally { + if (methodEntry != null) { + methodEntry.exit(1, invocation.getArguments()); + } + if (interfaceEntry != null) { + interfaceEntry.exit(); + } + ContextUtil.exit(); } } From 57c689259c3cc9265f66df596c86e0159eb7b2d7 Mon Sep 17 00:00:00 2001 From: liangl Date: Tue, 28 Apr 2020 22:19:00 +0800 Subject: [PATCH 7/8] [1416] BaseSentinelDubboFilter add getMethodName() and getInterfaceName() method --- .../dubbo/SentinelDubboConsumerFilter.java | 2 - .../SentinelDubboConsumerFilterTest.java | 41 +++++++------------ .../SentinelDubboProviderFilterTest.java | 8 +--- 3 files changed, 16 insertions(+), 35 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java index 5a95f371a0..588379ab9b 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java @@ -118,12 +118,10 @@ private Result asyncInvoke(Invoker invoker, Invocation invocation) { result.whenCompleteWithContext(new BiConsumer() { @Override public void accept(Result result, Throwable throwable) { - if (result.hasException()) { while (entryStack.size() > 0) { Entry entry = entryStack.pop(); Tracer.traceEntry(result.getException(), entry); entry.exit(); - } } } }); diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java index 6fa6aa2f48..4608b2a584 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java @@ -34,8 +34,10 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; +import org.apache.dubbo.rpc.AppResponse; import org.apache.dubbo.rpc.AsyncRpcResult; import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.InvokeMode; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcContext; @@ -110,9 +112,7 @@ public void testDegradeAsync() throws InterruptedException { when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); initDegradeRule(DubboUtils.getInterfaceName(invoker)); - Result result = requestGo(false, invoker, invocation); - verifyInvocationStructureForAsyncCall(invoker, invocation); - responseBack(result, invoker, invocation); + Result result = invokeDubboRpc(false, invoker, invocation); verifyInvocationStructureForCallFinish(invoker, invocation); assertEquals("normal", result.getValue()); @@ -142,9 +142,7 @@ public void testDegradeSync() throws InterruptedException { Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); initDegradeRule(DubboUtils.getInterfaceName(invoker)); - Result result = requestGo(false, invoker, invocation); - verifyInvocationStructure(invoker, invocation); - responseBack(result, invoker, invocation); + Result result = invokeDubboRpc(false, invoker, invocation); verifyInvocationStructureForCallFinish(invoker, invocation); assertEquals("normal", result.getValue()); @@ -193,7 +191,7 @@ public void testMethodFlowControlAsync() { @Test - public void testInvokeAsync() throws InterruptedException { + public void testInvokeAsync() { Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne(); Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); @@ -203,9 +201,8 @@ public void testInvokeAsync() throws InterruptedException { when(result.hasException()).thenReturn(false); when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> { verifyInvocationStructureForAsyncCall(invoker, invocation); - return result; + return result; }); - consumerFilter.invoke(invoker, invocation); verify(invoker).invoke(invocation); @@ -230,7 +227,6 @@ public void testInvokeSync() { consumerFilter.invoke(invoker, invocation); verify(invoker).invoke(invocation); - consumerFilter.listener().onMessage(result, invoker, invocation); Context context = ContextUtil.getContext(); assertNull(context); } @@ -403,26 +399,19 @@ public Result handle(Invoker invoker, Invocation invocation, BlockException e }); } - private Result invokeDubboRpc(boolean isException, Invoker invoker, Invocation invocation) { - return responseBack(requestGo(isException, invoker, invocation), invoker, invocation); - } - - private Result requestGo(boolean exception, Invoker invoker, Invocation currentInvocation) { - AsyncRpcResult result = null; - - if (exception) { - result = AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), currentInvocation); + private Result invokeDubboRpc(boolean exception, Invoker invoker, Invocation invocation) { + Result result = null; + InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation); + if (InvokeMode.SYNC == invokeMode) { + result = exception ? new AppResponse(new Exception("error")) : new AppResponse("normal"); } else { - result = AsyncRpcResult.newDefaultAsyncResult("normal", currentInvocation); + result = exception ? AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), invocation) : AsyncRpcResult.newDefaultAsyncResult("normal", invocation); } - when(invoker.invoke(currentInvocation)).thenReturn(result); - return consumerFilter.invoke(invoker, currentInvocation); + when(invoker.invoke(invocation)).thenReturn(result); + return consumerFilter.invoke(invoker, invocation); } - private Result responseBack(Result result, Invoker invoker, Invocation invocation) { - consumerFilter.listener().onMessage(result, invoker, invocation); - return result; - } + } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java index 529d801bb0..6a98437384 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java @@ -19,7 +19,6 @@ import com.alibaba.csp.sentinel.DubboTestUtil; import com.alibaba.csp.sentinel.Entry; import com.alibaba.csp.sentinel.EntryType; -import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; import com.alibaba.csp.sentinel.context.Context; import com.alibaba.csp.sentinel.context.ContextUtil; @@ -88,7 +87,6 @@ public void testInvoke() { filter.invoke(invoker, invocation); verify(invoker).invoke(invocation); - filter.listener().onMessage(result, invoker, invocation); Context context = ContextUtil.getContext(); assertNull(context); } @@ -119,11 +117,7 @@ private void verifyInvocationStructure(String originApplication, Invoker invoker DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); ResourceWrapper interfaceResource = interfaceNode.getId(); - if (DubboConfig.getDubboInterfaceGroupAndVersionEnabled()) { - assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName()); - } else { - assertEquals(invoker.getInterface().getName(), interfaceResource.getName()); - } + assertEquals(filter.getInterfaceName(invoker), interfaceResource.getName()); assertSame(EntryType.IN, interfaceResource.getEntryType()); // As SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); From 0766b9ca709483a4c06f68d7826a45092cc7cb71 Mon Sep 17 00:00:00 2001 From: liangl Date: Tue, 26 May 2020 23:39:37 +0800 Subject: [PATCH 8/8] [1416] replace Stack with LinkedList for improve performance [1416] replace Stack with LinkedList for improve performance --- .../dubbo/SentinelDubboConsumerFilter.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java index 588379ab9b..3d0e2d4cfb 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java @@ -32,7 +32,7 @@ import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.support.RpcUtils; -import java.util.Stack; +import java.util.LinkedList; import java.util.function.BiConsumer; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; @@ -108,32 +108,30 @@ private Result syncInvoke(Invoker invoker, Invocation invocation) { private Result asyncInvoke(Invoker invoker, Invocation invocation) { - Stack entryStack = new Stack<>(); + LinkedList queue = new LinkedList<>(); String methodResourceName = getMethodName(invoker, invocation); String interfaceResourceName = getInterfaceName(invoker); try { - entryStack.push(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT)); - entryStack.push(SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments())); + queue.push(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT)); + queue.push(SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments())); Result result = invoker.invoke(invocation); result.whenCompleteWithContext(new BiConsumer() { @Override public void accept(Result result, Throwable throwable) { - while (entryStack.size() > 0) { - Entry entry = entryStack.pop(); - Tracer.traceEntry(result.getException(), entry); - entry.exit(); + while (!queue.isEmpty()) { + Entry entry = queue.pop(); + Tracer.traceEntry(result.getException(), entry); + entry.exit(); } } }); return result; } catch (BlockException e) { - while (entryStack.size() > 0) { - entryStack.pop().exit(); + while (!queue.isEmpty()) { + queue.pop().exit(); } return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); } - - } }