This is an automated email from the ASF dual-hosted git repository. huxing pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/dubbo-sentinel-support.git
commit 751e796aecfee9c635407be67b8ab6d059e97651 Author: Eric Zhao <[email protected]> AuthorDate: Thu Apr 25 17:10:01 2019 +0800 Sync code and bump version to 1.6.0 Signed-off-by: Eric Zhao <[email protected]> --- README.md | 18 +-- pom.xml | 32 ++++- .../adapter/dubbo/AbstractDubboFilter.java | 44 ------ .../adapter/dubbo/DubboAppContextFilter.java | 18 +-- .../csp/sentinel/adapter/dubbo/DubboUtils.java | 25 +++- .../adapter/dubbo/SentinelDubboConsumerFilter.java | 31 +++-- .../adapter/dubbo/SentinelDubboProviderFilter.java | 35 +++-- .../dubbo/fallback/DefaultDubboFallback.java | 8 +- .../adapter/dubbo/fallback/DubboFallback.java | 9 +- .../dubbo/fallback/DubboFallbackRegistry.java | 11 +- ...ubbo.rpc.Filter => org.apache.dubbo.rpc.Filter} | 2 +- .../java/com/alibaba/csp/sentinel/BaseTest.java} | 34 ++--- .../csp/sentinel/adapter/dubbo/DemoService.java | 8 -- .../adapter/dubbo/DubboAppContextFilterTest.java | 80 +++++++++++ .../sentinel/adapter/dubbo/DubboConsumerTest.java | 74 ---------- .../sentinel/adapter/dubbo/DubboProviderTest.java | 32 ----- .../csp/sentinel/adapter/dubbo/DubboUtilsTest.java | 78 +++++++++++ .../dubbo/SentinelDubboConsumerFilterTest.java | 150 ++++++++++++++++++++ .../dubbo/SentinelDubboProviderFilterTest.java | 154 +++++++++++++++++++++ .../dubbo/fallback/DubboFallbackRegistryTest.java | 50 +++++++ .../adapter/dubbo/provider/DemoService.java} | 20 +-- .../adapter/dubbo/provider/DemoServiceImpl.java | 12 -- .../dubbo/provider/impl/DemoServiceImpl.java} | 20 +-- .../resources/spring-dubbo-consumer-filter.xml | 8 +- .../resources/spring-dubbo-provider-filter.xml | 8 +- 25 files changed, 665 insertions(+), 296 deletions(-) diff --git a/README.md b/README.md index da6bd23..fe97e9f 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,23 @@ -# Sentinel Dubbo Adapter +# Sentinel Apache Dubbo Adapter -> Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6%E7%9A%84%E9%80%82%E9%85%8D#dubbo)。 +> Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/主流框架的适配#dubbo)。 Sentinel Dubbo Adapter provides service consumer filter and provider filter -for [Dubbo](http://dubbo.io/) services. +for [Apache Dubbo](https://dubbo.apache.org/en-us/) services. + +**Note: This adapter only supports Apache Dubbo 2.7.x and above.** For legacy `com.alibaba:dubbo` 2.6.x, +please use `sentinel-dubbo-adapter` module instead. To use Sentinel Dubbo Adapter, you can simply add the following dependency to your `pom.xml`: ```xml <dependency> <groupId>com.alibaba.csp</groupId> - <artifactId>sentinel-dubbo-adapter</artifactId> + <artifactId>sentinel-apache-dubbo-adapter</artifactId> <version>x.y.z</version> </dependency> ``` -> Note: currently this adapter is not compatible with Dubbo 2.7.x due to its package renaming. -We are working to support the latest Dubbo version. - 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. @@ -31,7 +31,7 @@ If you don't want the filters enabled, you can manually disable them. For exampl <dubbo:provider filter="-sentinel.dubbo.provider.filter"/> ``` -For more details of Dubbo filter, see [here](https://dubbo.incubator.apache.org/#/docs/dev/impls/filter.md?lang=en-us). +For more details of Dubbo filter, see [here](http://dubbo.apache.org/en-us/docs/dev/impls/filter.html). ## Dubbo resources @@ -65,4 +65,4 @@ flow control, degrade or system load protection. You can implement your own `Dub and then register to `DubboFallbackRegistry`. If no fallback is configured, Sentinel will wrap the `BlockException` then directly throw it out. -Besides, we can also leverage [Dubbo mock mechanism](http://dubbo.apache.org/#!/docs/user/demos/local-mock.md?lang=en-us) to provide fallback implementation of degraded Dubbo services. \ No newline at end of file +Besides, we can also leverage [Dubbo mock mechanism](http://dubbo.apache.org/en-us/docs/user/demos/local-mock.html) to provide fallback implementation of degraded Dubbo services. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3ed33aa..dfd08bb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,33 +4,51 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>com.alibaba.csp</groupId> - <artifactId>sentinel-adapter</artifactId> - <version>1.4.2</version> - </parent> - <artifactId>sentinel-dubbo-adapter</artifactId> + <groupId>com.alibaba.csp</groupId> + <artifactId>sentinel-apache-dubbo-adapter</artifactId> + <version>1.6.0</version> <packaging>jar</packaging> + <properties> + <java.source.version>1.8</java.source.version> + <java.target.version>1.8</java.target.version> + + <sentinel.version>1.6.0</sentinel.version> + <apache.dubbo.version>2.7.1</apache.dubbo.version> + + <junit.version>4.12</junit.version> + <mockito.version>2.21.0</mockito.version> + </properties> + <dependencies> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> + <version>${sentinel.version}</version> </dependency> <dependency> - <groupId>com.alibaba</groupId> + <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> + <version>${apache.dubbo.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>${mockito.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> + <version>1.2.57</version> <scope>test</scope> </dependency> </dependencies> diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/AbstractDubboFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/AbstractDubboFilter.java deleted file mode 100755 index 2c5b077..0000000 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/AbstractDubboFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.adapter.dubbo; - -import com.alibaba.dubbo.rpc.Filter; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; - -/** - * @author leyou - */ -abstract class AbstractDubboFilter implements Filter { - - protected String getResourceName(Invoker<?> invoker, Invocation invocation) { - StringBuilder buf = new StringBuilder(64); - buf.append(invoker.getInterface().getName()) - .append(":") - .append(invocation.getMethodName()) - .append("("); - boolean isFirst = true; - for (Class<?> clazz : invocation.getParameterTypes()) { - if (!isFirst) { - buf.append(","); - } - buf.append(clazz.getName()); - isFirst = false; - } - buf.append(")"); - return buf.toString(); - } -} diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java index ceae979..97ae51b 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java @@ -15,14 +15,14 @@ */ package com.alibaba.csp.sentinel.adapter.dubbo; -import com.alibaba.dubbo.common.Constants; -import com.alibaba.dubbo.common.extension.Activate; -import com.alibaba.dubbo.rpc.Filter; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcContext; -import com.alibaba.dubbo.rpc.RpcException; +import org.apache.dubbo.common.Constants; +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; /** * Puts current consumer's application name in the attachment of each invocation. @@ -36,7 +36,7 @@ public class DubboAppContextFilter implements Filter { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { String application = invoker.getUrl().getParameter(Constants.APPLICATION_KEY); if (application != null) { - RpcContext.getContext().setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, application); + RpcContext.getContext().setAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, application); } return invoker.invoke(invocation); } diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java index f633e9e..03a494f 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java @@ -15,20 +15,39 @@ */ package com.alibaba.csp.sentinel.adapter.dubbo; -import com.alibaba.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; /** * @author Eric Zhao */ public final class DubboUtils { - public static final String DUBBO_APPLICATION_KEY = "dubboApplication"; + public static final String SENTINEL_DUBBO_APPLICATION_KEY = "dubboApplication"; public static String getApplication(Invocation invocation, String defaultValue) { if (invocation == null || invocation.getAttachments() == null) { throw new IllegalArgumentException("Bad invocation instance"); } - return invocation.getAttachment(DUBBO_APPLICATION_KEY, defaultValue); + return invocation.getAttachment(SENTINEL_DUBBO_APPLICATION_KEY, defaultValue); + } + + public static String getResourceName(Invoker<?> invoker, Invocation invocation) { + StringBuilder buf = new StringBuilder(64); + buf.append(invoker.getInterface().getName()) + .append(":") + .append(invocation.getMethodName()) + .append("("); + boolean isFirst = true; + for (Class<?> clazz : invocation.getParameterTypes()) { + if (!isFirst) { + buf.append(","); + } + buf.append(clazz.getName()); + isFirst = false; + } + buf.append(")"); + return buf.toString(); } private DubboUtils() {} diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java index 85b268d..6ca0d67 100755 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java @@ -20,15 +20,15 @@ import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.SphU; import com.alibaba.csp.sentinel.Tracer; 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 com.alibaba.dubbo.common.extension.Activate; -import com.alibaba.dubbo.rpc.Filter; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcException; + +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.RpcException; /** * <p>Dubbo service consumer filter for Sentinel. Auto activated by default.</p> @@ -38,14 +38,14 @@ import com.alibaba.dubbo.rpc.RpcException; * <dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/> * </pre> * - * @author leyou + * @author Carpenter Lee * @author Eric Zhao */ @Activate(group = "consumer") -public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements Filter { +public class SentinelDubboConsumerFilter implements Filter { public SentinelDubboConsumerFilter() { - RecordLog.info("Sentinel Dubbo consumer filter initialized"); + RecordLog.info("Sentinel Apache Dubbo consumer filter initialized"); } @Override @@ -53,21 +53,23 @@ public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements Entry interfaceEntry = null; Entry methodEntry = null; try { - String resourceName = getResourceName(invoker, invocation); - ContextUtil.enter(resourceName); + String resourceName = DubboUtils.getResourceName(invoker, invocation); interfaceEntry = SphU.entry(invoker.getInterface().getName(), EntryType.OUT); methodEntry = SphU.entry(resourceName, EntryType.OUT); Result result = invoker.invoke(invocation); if (result.hasException()) { + Throwable e = result.getException(); // Record common exception. - Tracer.trace(result.getException()); + Tracer.traceEntry(e, interfaceEntry); + Tracer.traceEntry(e, methodEntry); } return result; } catch (BlockException e) { return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); } catch (RpcException e) { - Tracer.trace(e); + Tracer.traceEntry(e, interfaceEntry); + Tracer.traceEntry(e, methodEntry); throw e; } finally { if (methodEntry != null) { @@ -76,7 +78,6 @@ public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements if (interfaceEntry != null) { interfaceEntry.exit(); } - ContextUtil.exit(); } } } diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java index c82afb8..2020832 100755 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java @@ -23,30 +23,31 @@ 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 com.alibaba.csp.sentinel.slots.block.SentinelRpcException; -import com.alibaba.dubbo.common.extension.Activate; -import com.alibaba.dubbo.rpc.Filter; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcException; + +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.RpcException; /** - * <p>Dubbo service provider filter for Sentinel. Auto activated by default.</p> + * <p>Apache Dubbo service provider filter that enables integration with Sentinel. Auto activated by default.</p> + * <p>Note: this only works for Apache Dubbo 2.7.x or above version.</p> * * If you want to disable the provider filter, you can configure: * <pre> * <dubbo:provider filter="-sentinel.dubbo.provider.filter"/> * </pre> * - * @author leyou + * @author Carpenter Lee * @author Eric Zhao */ @Activate(group = "provider") -public class SentinelDubboProviderFilter extends AbstractDubboFilter implements Filter { +public class SentinelDubboProviderFilter implements Filter { public SentinelDubboProviderFilter() { - RecordLog.info("Sentinel Dubbo provider filter initialized"); + RecordLog.info("Sentinel Apache Dubbo provider filter initialized"); } @Override @@ -57,21 +58,27 @@ public class SentinelDubboProviderFilter extends AbstractDubboFilter implements Entry interfaceEntry = null; Entry methodEntry = null; try { - String resourceName = getResourceName(invoker, invocation); + String resourceName = DubboUtils.getResourceName(invoker, invocation); String interfaceName = invoker.getInterface().getName(); + // 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(resourceName, application); interfaceEntry = SphU.entry(interfaceName, EntryType.IN); methodEntry = SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); Result result = invoker.invoke(invocation); if (result.hasException()) { - Tracer.trace(result.getException()); + Throwable e = result.getException(); + // Record common exception. + Tracer.traceEntry(e, interfaceEntry); + Tracer.traceEntry(e, methodEntry); } return result; } catch (BlockException e) { return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e); } catch (RpcException e) { - Tracer.trace(e); + Tracer.traceEntry(e, interfaceEntry); + Tracer.traceEntry(e, methodEntry); throw e; } finally { if (methodEntry != null) { diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java index e41b51b..8a4659f 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DefaultDubboFallback.java @@ -17,13 +17,13 @@ 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 com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; + +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; /** * @author Eric Zhao - * @since 0.1.1 */ public class DefaultDubboFallback implements DubboFallback { diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java index f529ae3..133232c 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java @@ -16,16 +16,17 @@ package com.alibaba.csp.sentinel.adapter.dubbo.fallback; import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; + +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; /** * Fallback handler for Dubbo services. * * @author Eric Zhao - * @since 0.1.1 */ +@FunctionalInterface public interface DubboFallback { /** diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java index 9f87e61..78c3a0b 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java +++ b/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistry.java @@ -15,14 +15,17 @@ */ package com.alibaba.csp.sentinel.adapter.dubbo.fallback; +import com.alibaba.csp.sentinel.util.AssertUtil; + /** - * Global fallback registry for Dubbo. + * <p>Global fallback registry for Dubbo.</p> * - * Note: Degrading is mainly designed for consumer. The provider should not + * <p> + * Note: Circuit breaking is mainly designed for consumer. The provider should not * give fallback result in most circumstances. + * </p> * * @author Eric Zhao - * @since 0.1.1 */ public final class DubboFallbackRegistry { @@ -34,6 +37,7 @@ public final class DubboFallbackRegistry { } public static void setConsumerFallback(DubboFallback consumerFallback) { + AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null"); DubboFallbackRegistry.consumerFallback = consumerFallback; } @@ -42,6 +46,7 @@ public final class DubboFallbackRegistry { } public static void setProviderFallback(DubboFallback providerFallback) { + AssertUtil.notNull(providerFallback, "providerFallback cannot be null"); DubboFallbackRegistry.providerFallback = providerFallback; } diff --git a/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter b/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter similarity index 88% rename from src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter rename to src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter index af7c961..292a4b2 100755 --- a/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter +++ b/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter @@ -1,3 +1,3 @@ sentinel.dubbo.provider.filter=com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboProviderFilter sentinel.dubbo.consumer.filter=com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboConsumerFilter -dubbo.application.context.name.filter=com.alibaba.csp.sentinel.adapter.dubbo.DubboAppContextFilter \ No newline at end of file +dubbo.application.context.name.filter=com.alibaba.csp.sentinel.adapter.dubbo.DubboAppContextFilter diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java b/src/test/java/com/alibaba/csp/sentinel/BaseTest.java similarity index 50% copy from src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java copy to src/test/java/com/alibaba/csp/sentinel/BaseTest.java index f529ae3..a61f3b4 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallback.java +++ b/src/test/java/com/alibaba/csp/sentinel/BaseTest.java @@ -13,28 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.dubbo.fallback; +package com.alibaba.csp.sentinel; -import com.alibaba.csp.sentinel.slots.block.BlockException; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; +import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; + +import org.apache.dubbo.rpc.RpcContext; /** - * Fallback handler for Dubbo services. + * Base test class, provide common methods for subClass + * The package is same as CtSph, to call CtSph.resetChainMap() method for test + * + * Note: Only for test. DO NOT USE IN PRODUCTION! * - * @author Eric Zhao - * @since 0.1.1 + * @author cdfive */ -public interface DubboFallback { +public class BaseTest { /** - * Handle the block exception and provide fallback result. - * - * @param invoker Dubbo invoker - * @param invocation Dubbo invocation - * @param ex block exception - * @return fallback result + * Clean up resources for context, clusterNodeMap, processorSlotChainMap */ - Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex); -} + protected static void cleanUpAll() { + RpcContext.removeContext(); + ClusterBuilderSlot.getClusterNodeMap().clear(); + CtSph.resetChainMap(); + } +} \ No newline at end of file diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DemoService.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DemoService.java deleted file mode 100755 index 8ccc4a0..0000000 --- a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DemoService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.alibaba.csp.sentinel.adapter.dubbo; - -/** - * @author leyou - */ -public interface DemoService { - String sayHello(String name, int n); -} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilterTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilterTest.java new file mode 100644 index 0000000..1f461ea --- /dev/null +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilterTest.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.adapter.dubbo; + +import com.alibaba.csp.sentinel.BaseTest; +import com.alibaba.csp.sentinel.adapter.dubbo.DubboAppContextFilter; +import com.alibaba.csp.sentinel.adapter.dubbo.DubboUtils; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author cdfive + */ +public class DubboAppContextFilterTest extends BaseTest { + + private DubboAppContextFilter filter = new DubboAppContextFilter(); + + @Before + public void setUp() { + cleanUpAll(); + } + + @After + public void cleanUp() { + cleanUpAll(); + } + + @Test + public void testInvokeApplicationKey() { + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + URL url = URL.valueOf("test://test:111/test?application=serviceA"); + when(invoker.getUrl()).thenReturn(url); + + filter.invoke(invoker, invocation); + verify(invoker).invoke(invocation); + + String application = RpcContext.getContext().getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY); + assertEquals("serviceA", application); + } + + @Test + public void testInvokeNullApplicationKey() { + Invoker invoker = mock(Invoker.class); + Invocation invocation = mock(Invocation.class); + URL url = URL.valueOf("test://test:111/test?application="); + when(invoker.getUrl()).thenReturn(url); + + filter.invoke(invoker, invocation); + verify(invoker).invoke(invocation); + + String application = RpcContext.getContext().getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY); + assertNull(application); + } +} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboConsumerTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboConsumerTest.java deleted file mode 100755 index 4ba0a4d..0000000 --- a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboConsumerTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.alibaba.csp.sentinel.adapter.dubbo; - -import java.util.Arrays; - -import com.alibaba.csp.sentinel.node.ClusterNode; -import com.alibaba.csp.sentinel.slots.block.RuleConstant; -import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; -import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; -import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * 运行该用例的时候需要加入JVM参数:-Djava.net.preferIPv4Stack=true, - * 否则可能会抛出{@code java.lang.IllegalStateException: Can't assign requested address} - * - * @author leyou - */ -public class DubboConsumerTest { - private final String resource = "com.alibaba.csp.sentinel.adapter.dubbo.DemoService:sayHello(java.lang.String,int)"; - private final String interfaceResource = "com.alibaba.csp.sentinel.adapter.dubbo.DemoService"; - private ClassPathXmlApplicationContext context; - - @Before - public void init() { - context = new ClassPathXmlApplicationContext( - new String[] {"spring-dubbo-consumer-filter.xml"}); - context.start(); - } - - @Test - public void testConsumerFilter() throws Exception { - DemoService demoService = (DemoService)context.getBean("demoService"); - String result = demoService.sayHello("Test dubbo consumer filter", 2); - System.out.println("result=" + result); - ClusterNode node = ClusterBuilderSlot.getClusterNode(resource); - Assert.assertNotNull(node); - } - - @Test(expected = SentinelRpcException.class) - public void testConsumerBlock() throws Exception { - FlowRule flowRule = new FlowRule(); - flowRule.setResource(resource); - flowRule.setCount(10); - flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); - flowRule.setLimitApp("default"); - FlowRuleManager.loadRules(Arrays.asList(flowRule)); - - DemoService demoService = (DemoService)context.getBean("demoService"); - for (int i = 0; i < 100; i++) { - demoService.sayHello("Test dubbo consumer filter", 2); - } - } - - @Test(expected = SentinelRpcException.class) - public void testConsumerBlock2() throws Exception { - FlowRule flowRule = new FlowRule(); - flowRule.setResource(interfaceResource); - flowRule.setCount(10); - flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); - flowRule.setLimitApp("default"); - FlowRuleManager.loadRules(Arrays.asList(flowRule)); - - DemoService demoService = (DemoService)context.getBean("demoService"); - for (int i = 0; i < 100; i++) { - demoService.sayHello("Test dubbo consumer filter", 2); - } - } - -} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboProviderTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboProviderTest.java deleted file mode 100755 index 8c4657e..0000000 --- a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboProviderTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.alibaba.csp.sentinel.adapter.dubbo; - -import com.alibaba.csp.sentinel.node.ClusterNode; -import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** - * 运行该用例的时候需要加入JVM参数:-Djava.net.preferIPv4Stack=true, - * 否则可能会抛出{@code java.lang.IllegalStateException: Can't assign requested address} - * - * @author leyou - */ -public class DubboProviderTest { - - private final String resource = "com.alibaba.csp.sentinel.adapter.dubbo.DemoService:sayHello(java.lang.String,int)"; - - @Test - public void testProviderFilter() throws Exception { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( - new String[] {"spring-dubbo-provider-filter.xml"}); - context.start(); - DemoService demoService = (DemoService)context.getBean("demoService"); - String result = demoService.sayHello("Test dubbo provider filter", 1); - System.out.println("result=" + result); - ClusterNode node = ClusterBuilderSlot.getClusterNode(resource); - Thread.sleep(1000 * 60 * 100); - Assert.assertNotNull(node); - } -} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java new file mode 100644 index 0000000..e06c85d --- /dev/null +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtilsTest.java @@ -0,0 +1,78 @@ +/* + * 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.adapter.dubbo; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import com.alibaba.csp.sentinel.adapter.dubbo.DubboUtils; +import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; + +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.junit.Test; + +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; + +/** + * @author cdfive + */ +public class DubboUtilsTest { + + @Test + public void testGetApplication() { + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachments()).thenReturn(new HashMap<>()); + when(invocation.getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, "")) + .thenReturn("consumerA"); + + String application = DubboUtils.getApplication(invocation, ""); + verify(invocation).getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, ""); + + assertEquals("consumerA", application); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetApplicationNoAttachments() { + Invocation invocation = mock(Invocation.class); + when(invocation.getAttachments()).thenReturn(null); + when(invocation.getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, "")) + .thenReturn("consumerA"); + + DubboUtils.getApplication(invocation, ""); + + fail("No attachments in invocation, IllegalArgumentException should be thrown!"); + } + + @Test + public void testGetResourceName() { + Invoker invoker = mock(Invoker.class); + when(invoker.getInterface()).thenReturn(DemoService.class); + + Invocation invocation = mock(Invocation.class); + Method method = DemoService.class.getMethods()[0]; + when(invocation.getMethodName()).thenReturn(method.getName()); + when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); + + String resourceName = DubboUtils.getResourceName(invoker, invocation); + + assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); + } +} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java new file mode 100644 index 0000000..e737fd1 --- /dev/null +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilterTest.java @@ -0,0 +1,150 @@ +/* + * 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.adapter.dubbo; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +import com.alibaba.csp.sentinel.BaseTest; +import com.alibaba.csp.sentinel.Constants; +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.adapter.dubbo.DubboUtils; +import com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboConsumerFilter; +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; +import com.alibaba.csp.sentinel.node.DefaultNode; +import com.alibaba.csp.sentinel.node.Node; +import com.alibaba.csp.sentinel.node.StatisticNode; +import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; + +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +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; + +/** + * @author cdfive + */ +public class SentinelDubboConsumerFilterTest extends BaseTest { + + private SentinelDubboConsumerFilter filter = new SentinelDubboConsumerFilter(); + + @Before + public void setUp() { + cleanUpAll(); + } + + @After + public void cleanUp() { + cleanUpAll(); + } + + @Test + public void testInvoke() { + final Invoker invoker = mock(Invoker.class); + when(invoker.getInterface()).thenReturn(DemoService.class); + + final Invocation invocation = mock(Invocation.class); + Method method = DemoService.class.getMethods()[0]; + when(invocation.getMethodName()).thenReturn(method.getName()); + when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); + + final Result result = mock(Result.class); + when(result.hasException()).thenReturn(false); + when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> { + verifyInvocationStructure(invoker, invocation); + return result; + }); + + filter.invoke(invoker, invocation); + verify(invoker).invoke(invocation); + + Context context = ContextUtil.getContext(); + assertNull(context); + } + + /** + * Simply verify invocation structure in memory: + * EntranceNode(defaultContextName) + * --InterfaceNode(interfaceName) + * ----MethodNode(resourceName) + */ + private void verifyInvocationStructure(Invoker invoker, Invocation invocation) { + 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 + // If consumer is on the top of Dubbo RPC invocation chain, use default context + String resourceName = DubboUtils.getResourceName(invoker, invocation); + assertEquals(Constants.CONTEXT_DEFAULT_NAME, context.getName()); + assertEquals("", context.getOrigin()); + + DefaultNode entranceNode = context.getEntranceNode(); + ResourceWrapper entranceResource = entranceNode.getId(); + assertEquals(Constants.CONTEXT_DEFAULT_NAME, entranceResource.getName()); + assertSame(EntryType.IN, entranceResource.getType()); + + // As SphU.entry(interfaceName, EntryType.OUT); + Set<Node> childList = entranceNode.getChildList(); + assertEquals(1, childList.size()); + DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); + ResourceWrapper interfaceResource = interfaceNode.getId(); + assertEquals(DemoService.class.getName(), interfaceResource.getName()); + assertSame(EntryType.OUT, interfaceResource.getType()); + + // As SphU.entry(resourceName, EntryType.OUT); + childList = interfaceNode.getChildList(); + assertEquals(1, childList.size()); + DefaultNode methodNode = (DefaultNode) childList.iterator().next(); + ResourceWrapper methodResource = methodNode.getId(); + assertEquals(resourceName, methodResource.getName()); + assertSame(EntryType.OUT, methodResource.getType()); + + // Verify curEntry + Entry curEntry = context.getCurEntry(); + assertSame(methodNode, curEntry.getCurNode()); + assertSame(interfaceNode, curEntry.getLastNode()); + assertNull(curEntry.getOriginNode());// As context origin is not "", no originNode should be created in curEntry + + // Verify clusterNode + ClusterNode methodClusterNode = methodNode.getClusterNode(); + ClusterNode interfaceClusterNode = interfaceNode.getClusterNode(); + assertNotSame(methodClusterNode, interfaceClusterNode);// Different resource->Different ProcessorSlot->Different ClusterNode + + // As context origin is "", the StatisticNode should not be created in originCountMap of ClusterNode + Map<String, StatisticNode> methodOriginCountMap = methodClusterNode.getOriginCountMap(); + assertEquals(0, methodOriginCountMap.size()); + + Map<String, StatisticNode> interfaceOriginCountMap = interfaceClusterNode.getOriginCountMap(); + assertEquals(0, interfaceOriginCountMap.size()); + } +} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java new file mode 100644 index 0000000..af858b1 --- /dev/null +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilterTest.java @@ -0,0 +1,154 @@ +/* + * 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.adapter.dubbo; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +import com.alibaba.csp.sentinel.BaseTest; +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.adapter.dubbo.DubboUtils; +import com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboProviderFilter; +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; +import com.alibaba.csp.sentinel.node.DefaultNode; +import com.alibaba.csp.sentinel.node.Node; +import com.alibaba.csp.sentinel.node.StatisticNode; +import com.alibaba.csp.sentinel.slotchain.ResourceWrapper; + +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +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; + +/** + * @author cdfive + */ +public class SentinelDubboProviderFilterTest extends BaseTest { + + private SentinelDubboProviderFilter filter = new SentinelDubboProviderFilter(); + + @Before + public void setUp() { + cleanUpAll(); + } + + @After + public void cleanUp() { + cleanUpAll(); + } + + @Test + public void testInvoke() { + final String originApplication = "consumerA"; + + final Invoker invoker = mock(Invoker.class); + when(invoker.getInterface()).thenReturn(DemoService.class); + + final Invocation invocation = mock(Invocation.class); + Method method = DemoService.class.getMethods()[0]; + when(invocation.getMethodName()).thenReturn(method.getName()); + when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); + when(invocation.getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, "")) + .thenReturn(originApplication); + + final Result result = mock(Result.class); + when(result.hasException()).thenReturn(false); + when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> { + verifyInvocationStructure(originApplication, invoker, invocation); + return result; + }); + + filter.invoke(invoker, invocation); + verify(invoker).invoke(invocation); + + Context context = ContextUtil.getContext(); + assertNull(context); + } + + /** + * Simply verify invocation structure in memory: + * EntranceNode(resourceName) + * --InterfaceNode(interfaceName) + * ----MethodNode(resourceName) + */ + 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); + assertEquals(resourceName, context.getName()); + assertEquals(originApplication, context.getOrigin()); + + DefaultNode entranceNode = context.getEntranceNode(); + ResourceWrapper entranceResource = entranceNode.getId(); + assertEquals(resourceName, entranceResource.getName()); + assertSame(EntryType.IN, entranceResource.getType()); + + // As SphU.entry(interfaceName, EntryType.IN); + Set<Node> childList = entranceNode.getChildList(); + assertEquals(1, childList.size()); + DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); + ResourceWrapper interfaceResource = interfaceNode.getId(); + assertEquals(DemoService.class.getName(), interfaceResource.getName()); + assertSame(EntryType.IN, interfaceResource.getType()); + + // As SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); + childList = interfaceNode.getChildList(); + assertEquals(1, childList.size()); + DefaultNode methodNode = (DefaultNode) childList.iterator().next(); + ResourceWrapper methodResource = methodNode.getId(); + assertEquals(resourceName, methodResource.getName()); + assertSame(EntryType.IN, methodResource.getType()); + + // Verify curEntry + Entry curEntry = context.getCurEntry(); + assertSame(methodNode, curEntry.getCurNode()); + assertSame(interfaceNode, curEntry.getLastNode()); + assertNotNull(curEntry.getOriginNode());// As context origin is not "", originNode should be created + + // Verify clusterNode + ClusterNode methodClusterNode = methodNode.getClusterNode(); + ClusterNode interfaceClusterNode = interfaceNode.getClusterNode(); + assertNotSame(methodClusterNode, interfaceClusterNode);// Different resource->Different ProcessorSlot->Different ClusterNode + + // As context origin is not "", the StatisticNode should be created in originCountMap of ClusterNode + Map<String, StatisticNode> methodOriginCountMap = methodClusterNode.getOriginCountMap(); + assertEquals(1, methodOriginCountMap.size()); + assertTrue(methodOriginCountMap.containsKey(originApplication)); + + Map<String, StatisticNode> interfaceOriginCountMap = interfaceClusterNode.getOriginCountMap(); + assertEquals(1, interfaceOriginCountMap.size()); + assertTrue(interfaceOriginCountMap.containsKey(originApplication)); + } +} diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java new file mode 100644 index 0000000..bc06ebf --- /dev/null +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/fallback/DubboFallbackRegistryTest.java @@ -0,0 +1,50 @@ +/* + * 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.adapter.dubbo.fallback; + +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.Result; +import org.apache.dubbo.rpc.RpcResult; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Eric Zhao + */ +public class DubboFallbackRegistryTest { + + @Test(expected = SentinelRpcException.class) + public void testDefaultFallback() { + // Test for default. + BlockException ex = new FlowException("xxx"); + DubboFallbackRegistry.getConsumerFallback() + .handle(null, null, ex); + } + + @Test + public void testCustomFallback() { + BlockException ex = new FlowException("xxx"); + DubboFallbackRegistry.setConsumerFallback( + (invoker, invocation, e) -> new RpcResult("Error: " + e.getClass().getName())); + Result result = DubboFallbackRegistry.getConsumerFallback() + .handle(null, null, ex); + Assert.assertFalse("The invocation should not fail", result.hasException()); + Assert.assertEquals("Error: " + ex.getClass().getName(), result.getValue()); + } +} diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoService.java similarity index 52% copy from src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java copy to src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoService.java index f633e9e..2a024cc 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoService.java @@ -13,23 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.dubbo; - -import com.alibaba.dubbo.rpc.Invocation; +package com.alibaba.csp.sentinel.adapter.dubbo.provider; /** - * @author Eric Zhao + * @author leyou */ -public final class DubboUtils { - - public static final String DUBBO_APPLICATION_KEY = "dubboApplication"; - - public static String getApplication(Invocation invocation, String defaultValue) { - if (invocation == null || invocation.getAttachments() == null) { - throw new IllegalArgumentException("Bad invocation instance"); - } - return invocation.getAttachment(DUBBO_APPLICATION_KEY, defaultValue); - } - - private DubboUtils() {} +public interface DemoService { + String sayHello(String name, int n); } diff --git a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoServiceImpl.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoServiceImpl.java deleted file mode 100755 index db566e7..0000000 --- a/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/DemoServiceImpl.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.alibaba.csp.sentinel.adapter.dubbo.provider; - -import com.alibaba.csp.sentinel.adapter.dubbo.DemoService; - -/** - * @author leyou - */ -public class DemoServiceImpl implements DemoService { - public String sayHello(String name, int n) { - return "Hello " + name + ", " + n; - } -} diff --git a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/impl/DemoServiceImpl.java similarity index 52% copy from src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java copy to src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/impl/DemoServiceImpl.java index f633e9e..f804c2c 100644 --- a/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java +++ b/src/test/java/com/alibaba/csp/sentinel/adapter/dubbo/provider/impl/DemoServiceImpl.java @@ -13,23 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.dubbo; +package com.alibaba.csp.sentinel.adapter.dubbo.provider.impl; -import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; /** - * @author Eric Zhao + * @author leyou */ -public final class DubboUtils { - - public static final String DUBBO_APPLICATION_KEY = "dubboApplication"; - - public static String getApplication(Invocation invocation, String defaultValue) { - if (invocation == null || invocation.getAttachments() == null) { - throw new IllegalArgumentException("Bad invocation instance"); - } - return invocation.getAttachment(DUBBO_APPLICATION_KEY, defaultValue); +public class DemoServiceImpl implements DemoService { + public String sayHello(String name, int n) { + return "Hello " + name + ", " + n; } - - private DubboUtils() {} } diff --git a/src/test/resources/spring-dubbo-consumer-filter.xml b/src/test/resources/spring-dubbo-consumer-filter.xml index ae0a89d..b129cc9 100755 --- a/src/test/resources/spring-dubbo-consumer-filter.xml +++ b/src/test/resources/spring-dubbo-consumer-filter.xml @@ -10,11 +10,9 @@ <dubbo:application name="demo-consumer"/> <dubbo:registry address="multicast://224.5.6.7:1234"/> <dubbo:protocol name="dubbo" port="20880"/> - <dubbo:service interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService" ref="demoServiceImp" /> - <bean id="demoServiceImp" class="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoServiceImpl"/> + <dubbo:service interface="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService" ref="demoServiceImp" /> + <bean id="demoServiceImp" class="com.alibaba.csp.sentinel.adapter.dubbo.provider.impl.DemoServiceImpl"/> - <dubbo:reference id="demoService" interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService"/> - - <dubbo:consumer filter="sentinel.dubbo.consumer.filter" /> + <dubbo:reference id="demoService" interface="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService"/> </beans> \ No newline at end of file diff --git a/src/test/resources/spring-dubbo-provider-filter.xml b/src/test/resources/spring-dubbo-provider-filter.xml index 0990c39..bc4a8fb 100755 --- a/src/test/resources/spring-dubbo-provider-filter.xml +++ b/src/test/resources/spring-dubbo-provider-filter.xml @@ -10,11 +10,9 @@ <dubbo:application name="demo-provider"/> <dubbo:registry address="multicast://224.5.6.7:1234"/> <dubbo:protocol name="dubbo" port="20880"/> - <dubbo:service interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService" ref="demoServiceImp" /> - <bean id="demoServiceImp" class="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoServiceImpl"/> + <dubbo:service interface="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService" ref="demoServiceImp" /> + <bean id="demoServiceImp" class="com.alibaba.csp.sentinel.adapter.dubbo.provider.impl.DemoServiceImpl"/> - <dubbo:reference id="demoService" interface="com.alibaba.csp.sentinel.adapter.dubbo.DemoService"/> - - <dubbo:provider filter="sentinel.dubbo.provider.filter" /> + <dubbo:reference id="demoService" interface="com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService"/> </beans> \ No newline at end of file
