From 5905874dd8fabc671fd9d996a2d56a7d493614c1 Mon Sep 17 00:00:00 2001 From: Eric Zhao Date: Wed, 19 Aug 2020 21:59:17 +0800 Subject: [PATCH] Fix NPE bug and improve default fallback in Dubbo 2.7.x adapter - Fix NPE bug in consumer filter (when non-biz error occurred) - Improve default fallback in Dubbo 2.7.x adapter: convert the BlockException to a simple RuntimeException (with necessary message) - Polish code and comments Signed-off-by: Eric Zhao --- .../sentinel-apache-dubbo-adapter/README.md | 8 +-- .../dubbo/BaseSentinelDubboFilter.java | 3 +- .../dubbo/SentinelDubboConsumerFilter.java | 35 +++++++------ .../dubbo/SentinelDubboProviderFilter.java | 5 +- .../config/DubboAdapterGlobalConfig.java | 12 ----- .../dubbo/fallback/DefaultDubboFallback.java | 4 +- .../dubbo/fallback/DubboFallbackRegistry.java | 10 +--- .../SentinelDubboConsumerFilterTest.java | 50 +++++++------------ .../fallback/DubboFallbackRegistryTest.java | 14 +++--- 9 files changed, 59 insertions(+), 82 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/README.md b/sentinel-adapter/sentinel-apache-dubbo-adapter/README.md index f46cf41d..9d232bef 100755 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/README.md +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/README.md @@ -1,4 +1,4 @@ -# Sentinel Apache Dubbo Adapter +# Sentinel Apache Dubbo Adapter (for 2.7.x+) > Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/主流框架的适配#dubbo)。 @@ -21,7 +21,7 @@ To use Sentinel Dubbo Adapter, you can simply add the following dependency to yo The Sentinel filters are **enabled by default**. Once you add the dependency, the Dubbo services and methods will become protected resources in Sentinel, which can leverage Sentinel's flow control and guard ability when rules are configured. -Demos can be found in [sentinel-demo-dubbo](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-dubbo). +Demos can be found in [sentinel-demo-apache-dubbo](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-apache-dubbo). If you don't want the filters enabled, you can manually disable them. For example: @@ -37,8 +37,8 @@ For more details of Dubbo filter, see [here](http://dubbo.apache.org/en-us/docs/ The resource for Dubbo services has two granularities: service interface and service method. -- Service interface:resourceName format is `interfaceName`,e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService` -- Service method:resourceName format is `interfaceName:methodSignature`,e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)` +- Service interface: resourceName format is `interfaceName`, e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService` +- Service method: resourceName format is `interfaceName:methodSignature`, e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)` ## Flow control based on caller 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 323fa122..8d4009f2 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 @@ -21,11 +21,10 @@ import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; /** - * Base Class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}. + * Base class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}. * * @author Zechao Zheng */ - public abstract class BaseSentinelDubboFilter implements Filter { 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 41f3acb6..02b8c5ad 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,11 +19,13 @@ import com.alibaba.csp.sentinel.*; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; 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.*; import org.apache.dubbo.rpc.support.RpcUtils; import java.util.LinkedList; +import java.util.Optional; import java.util.function.BiConsumer; import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; @@ -38,6 +40,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER; * * @author Carpenter Lee * @author Eric Zhao + * @author Lin Liang */ @Activate(group = CONSUMER) public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { @@ -64,7 +67,6 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { } else { return asyncInvoke(invoker, invocation); } - } private Result syncInvoke(Invoker invoker, Invocation invocation) { @@ -75,7 +77,8 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { String methodResourceName = getMethodName(invoker, invocation, prefix); try { interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); - methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); + methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, + invocation.getArguments()); Result result = invoker.invoke(invocation); if (result.hasException()) { Tracer.traceEntry(result.getException(), interfaceEntry); @@ -98,24 +101,27 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { } } - private Result asyncInvoke(Invoker invoker, Invocation invocation) { LinkedList queue = new LinkedList<>(); String prefix = DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey(); String interfaceResourceName = getInterfaceName(invoker, prefix); String methodResourceName = getMethodName(invoker, invocation, prefix); try { - queue.push(new EntryHolder(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT), null)); - queue.push(new EntryHolder(SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments()), invocation.getArguments())); + queue.push(new EntryHolder( + SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT), null)); + queue.push(new EntryHolder( + SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, + EntryType.OUT, 1, invocation.getArguments()), invocation.getArguments())); Result result = invoker.invoke(invocation); - result.whenCompleteWithContext(new BiConsumer() { - @Override - public void accept(Result result, Throwable throwable) { - while (!queue.isEmpty()) { - EntryHolder holder = queue.pop(); - Tracer.traceEntry(result.getException(), holder.entry); - exitEntry(holder); - } + result.whenCompleteWithContext((r, throwable) -> { + Throwable error = throwable; + if (error == null) { + error = Optional.ofNullable(r).map(Result::getException).orElse(null); + } + while (!queue.isEmpty()) { + EntryHolder holder = queue.pop(); + Tracer.traceEntry(error, holder.entry); + exitEntry(holder); } }); return result; @@ -127,10 +133,9 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { } } - class EntryHolder { + static class EntryHolder { final private Entry entry; - final private Object[] params; public EntryHolder(Entry entry, Object[] params) { 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 b8dc5fd6..867073e1 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 @@ -20,6 +20,7 @@ import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; 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.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -74,7 +75,8 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter { // at entrance of invocation chain only (for inbound traffic). ContextUtil.enter(methodResourceName, origin); interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN); - methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments()); + methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, + invocation.getArguments()); Result result = invoker.invoke(invocation); if (result.hasException()) { Tracer.traceEntry(result.getException(), interfaceEntry); @@ -98,6 +100,5 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter { } } - } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/config/DubboAdapterGlobalConfig.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/config/DubboAdapterGlobalConfig.java index b9cf9489..43664f0a 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/config/DubboAdapterGlobalConfig.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/config/DubboAdapterGlobalConfig.java @@ -43,13 +43,11 @@ public final class DubboAdapterGlobalConfig { private static final String DEFAULT_DUBBO_CONSUMER_PREFIX = "dubbo:consumer:"; public static final String DUBBO_INTERFACE_GROUP_VERSION_ENABLED = "csp.sentinel.dubbo.interface.group.version.enabled"; - public static final String TRACE_BIZ_EXCEPTION_ENABLED = "csp.sentinel.dubbo.trace.biz.exception.enabled"; private static volatile DubboFallback consumerFallback = new DefaultDubboFallback(); private static volatile DubboFallback providerFallback = new DefaultDubboFallback(); private static volatile DubboOriginParser originParser = new DefaultDubboOriginParser(); - public static boolean isUsePrefix() { return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_RES_NAME_WITH_PREFIX_KEY)); } @@ -74,16 +72,6 @@ public final class DubboAdapterGlobalConfig { return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED)); } - public static Boolean getDubboBizExceptionTraceEnabled() { - String traceBizExceptionEnabled = SentinelConfig.getConfig(TRACE_BIZ_EXCEPTION_ENABLED); - if (StringUtil.isNotBlank(traceBizExceptionEnabled)) { - return TRUE_STR.equalsIgnoreCase(traceBizExceptionEnabled); - } - return true; - } - - - public static DubboFallback getConsumerFallback() { return consumerFallback; } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java index 159d1dbe..d5099b1d 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java @@ -16,7 +16,7 @@ package com.alibaba.csp.sentinel.adapter.dubbo.fallback; import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; + import org.apache.dubbo.rpc.AsyncRpcResult; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -30,6 +30,6 @@ public class DefaultDubboFallback implements DubboFallback { @Override public Result handle(Invoker invoker, Invocation invocation, BlockException ex) { // Just wrap the exception. - return AsyncRpcResult.newDefaultAsyncResult(null, new SentinelRpcException(ex), invocation); + return AsyncRpcResult.newDefaultAsyncResult(ex.toRuntimeException(), invocation); } } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java index 9c887c13..a9fb1f5a 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java @@ -16,18 +16,14 @@ package com.alibaba.csp.sentinel.adapter.dubbo.fallback; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; -import com.alibaba.csp.sentinel.util.AssertUtil; /** *

Global fallback registry for Dubbo.

* - *

- * Note: Circuit breaking is mainly designed for consumer. The provider should not - * give fallback result in most circumstances. - *

- * * @author Eric Zhao + * @deprecated use {@link DubboAdapterGlobalConfig} instead since 1.8.0. */ +@Deprecated public final class DubboFallbackRegistry { public static DubboFallback getConsumerFallback() { @@ -35,7 +31,6 @@ public final class DubboFallbackRegistry { } public static void setConsumerFallback(DubboFallback consumerFallback) { - AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null"); DubboAdapterGlobalConfig.setConsumerFallback(consumerFallback); } @@ -44,7 +39,6 @@ public final class DubboFallbackRegistry { } public static void setProviderFallback(DubboFallback providerFallback) { - AssertUtil.notNull(providerFallback, "providerFallback cannot be null"); DubboAdapterGlobalConfig.setProviderFallback(providerFallback); } 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 c97cdbd5..a350a47d 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,6 +19,7 @@ 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.DubboAdapterGlobalConfig; 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; @@ -34,6 +35,7 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; 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.*; import org.apache.dubbo.rpc.support.RpcUtils; import org.junit.After; @@ -53,8 +55,7 @@ import static org.mockito.Mockito.*; */ public class SentinelDubboConsumerFilterTest extends BaseTest { - private SentinelDubboConsumerFilter consumerFilter = new SentinelDubboConsumerFilter(); - + private final SentinelDubboConsumerFilter consumerFilter = new SentinelDubboConsumerFilter(); @Before public void setUp() { @@ -67,7 +68,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { cleanUpAll(); } - @Test public void testInterfaceLevelFollowControlAsync() throws InterruptedException { @@ -105,7 +105,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { verifyInvocationStructureForCallFinish(invoker, invocation); assertEquals("normal", result.getValue()); - // inc the clusterNode's exception to trigger the fallback for (int i = 0; i < 5; i++) { invokeDubboRpc(true, invoker, invocation); @@ -153,7 +152,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { assertNull(context); } - @Test public void testMethodFlowControlAsync() { @@ -175,10 +173,8 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { assertEquals("fallback", fallback.getValue()); verifyInvocationStructureForCallFinish(invoker, invocation); - } - @Test public void testInvokeAsync() { @@ -190,7 +186,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { 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); @@ -220,7 +216,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { assertNull(context); } - /** * Simply verify invocation structure in memory: * EntranceNode(defaultContextName) @@ -231,7 +226,8 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { Context context = ContextUtil.getContext(); assertNotNull(context); // 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 + // 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 = consumerFilter.getMethodName(invoker, invocation, null); assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); @@ -269,7 +265,8 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { // Verify clusterNode ClusterNode methodClusterNode = methodNode.getClusterNode(); ClusterNode interfaceClusterNode = interfaceNode.getClusterNode(); - assertNotSame(methodClusterNode, interfaceClusterNode);// Different resource->Different ProcessorSlot->Different ClusterNode + assertNotSame(methodClusterNode, + interfaceClusterNode);// Different resource->Different ProcessorSlot->Different ClusterNode // As context origin is "", the StatisticNode should not be created in originCountMap of ClusterNode Map methodOriginCountMap = methodClusterNode.getOriginCountMap(); @@ -284,7 +281,8 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { assertNotNull(context); // 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 + // 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 = consumerFilter.getMethodName(invoker, invocation, null); assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); @@ -319,7 +317,8 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { // Verify clusterNode ClusterNode methodClusterNode = methodNode.getClusterNode(); ClusterNode interfaceClusterNode = interfaceNode.getClusterNode(); - assertNotSame(methodClusterNode, interfaceClusterNode);// Different resource->Different ProcessorSlot->Different ClusterNode + assertNotSame(methodClusterNode, + interfaceClusterNode);// Different resource->Different ProcessorSlot->Different ClusterNode // As context origin is "", the StatisticNode should not be created in originCountMap of ClusterNode Map methodOriginCountMap = methodClusterNode.getOriginCountMap(); @@ -329,7 +328,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { assertEquals(0, interfaceOriginCountMap.size()); } - private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) { Context context = ContextUtil.getContext(); assertNull(context); @@ -338,7 +336,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { assertNull(entries); } - private DefaultNode getNode(String resourceName, DefaultNode root) { Queue queue = new LinkedList<>(); @@ -355,7 +352,6 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { return null; } - private void initFlowRule(String resource) { FlowRule flowRule = new FlowRule(resource); flowRule.setCount(1); @@ -367,24 +363,18 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { private void initDegradeRule(String resource) { DegradeRule degradeRule = new DegradeRule(resource) - .setCount(0.5) - .setGrade(DEGRADE_GRADE_EXCEPTION_RATIO); + .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; - } + DubboAdapterGlobalConfig.setConsumerFallback((invoker, invocation, ex) -> { + // boolean async = RpcUtils.isAsync(invoker.getUrl(), invocation); + return AsyncRpcResult.newDefaultAsyncResult("fallback", invocation); }); } @@ -394,13 +384,11 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { if (InvokeMode.SYNC == invokeMode) { result = exception ? new AppResponse(new Exception("error")) : new AppResponse("normal"); } else { - result = exception ? AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), invocation) : AsyncRpcResult.newDefaultAsyncResult("normal", invocation); + result = exception ? AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), invocation) + : AsyncRpcResult.newDefaultAsyncResult("normal", invocation); } when(invoker.invoke(invocation)).thenReturn(result); return consumerFilter.invoke(invoker, invocation); } - - - } diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java index 9a3bdeb3..6c2f427c 100644 --- a/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java +++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java @@ -17,8 +17,8 @@ package com.alibaba.csp.sentinel.adapter.dubbo.fallback; import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; import com.alibaba.csp.sentinel.slots.block.flow.FlowException; + import org.apache.dubbo.rpc.AsyncRpcResult; import org.apache.dubbo.rpc.Result; import org.junit.After; @@ -33,12 +33,12 @@ public class DubboFallbackRegistryTest { @Before public void setUp() { - DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); + DubboAdapterGlobalConfig.setConsumerFallback(new DefaultDubboFallback()); } @After public void tearDown() { - DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); + DubboAdapterGlobalConfig.setConsumerFallback(new DefaultDubboFallback()); } @Test @@ -46,15 +46,17 @@ public class DubboFallbackRegistryTest { // Test for default fallback. BlockException ex = new FlowException("xxx"); Result result = new DefaultDubboFallback().handle(null, null, ex); - Assert.assertTrue("The invocation should not fail",result.hasException()); - Assert.assertEquals(SentinelRpcException.class, result.getException().getClass()); + Assert.assertTrue("The result should carry exception", result.hasException()); + Assert.assertTrue(BlockException.isBlockException(result.getException())); + Assert.assertTrue(result.getException().getMessage().contains(ex.getClass().getSimpleName())); } @Test public void testCustomFallback() { BlockException ex = new FlowException("xxx"); DubboAdapterGlobalConfig.setConsumerFallback( - (invoker, invocation, e) -> AsyncRpcResult.newDefaultAsyncResult("Error: " + e.getClass().getName(), invocation)); + (invoker, invocation, e) -> AsyncRpcResult + .newDefaultAsyncResult("Error: " + e.getClass().getName(), invocation)); Result result = DubboAdapterGlobalConfig.getConsumerFallback() .handle(null, null, ex); Assert.assertFalse("The invocation should not fail", result.hasException());