- copied legacy code and adapts to new package - also update document for legacy Dubbo adapter Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -17,6 +17,7 @@ | |||||
<modules> | <modules> | ||||
<module>sentinel-web-servlet</module> | <module>sentinel-web-servlet</module> | ||||
<module>sentinel-dubbo-adapter</module> | <module>sentinel-dubbo-adapter</module> | ||||
<module>sentinel-apache-dubbo-adapter</module> | |||||
<module>sentinel-grpc-adapter</module> | <module>sentinel-grpc-adapter</module> | ||||
<module>sentinel-zuul-adapter</module> | <module>sentinel-zuul-adapter</module> | ||||
<module>sentinel-reactor-adapter</module> | <module>sentinel-reactor-adapter</module> | ||||
@@ -0,0 +1,68 @@ | |||||
# Sentinel Apache Dubbo Adapter | |||||
> Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/主流框架的适配#dubbo)。 | |||||
Sentinel Dubbo Adapter provides service consumer filter and provider filter | |||||
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-apache-dubbo-adapter</artifactId> | |||||
<version>x.y.z</version> | |||||
</dependency> | |||||
``` | |||||
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). | |||||
If you don't want the filters enabled, you can manually disable them. For example: | |||||
```xml | |||||
<dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/> | |||||
<dubbo:provider filter="-sentinel.dubbo.provider.filter"/> | |||||
``` | |||||
For more details of Dubbo filter, see [here](http://dubbo.apache.org/en-us/docs/dev/impls/filter.html). | |||||
## Dubbo resources | |||||
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)` | |||||
## Flow control based on caller | |||||
In many circumstances, it's also significant to control traffic flow based on the **caller**. | |||||
For example, assuming that there are two services A and B, both of them initiate remote call requests to the service provider. | |||||
If we want to limit the calls from service B only, we can set the `limitApp` of flow rule as the identifier of service B (e.g. service name). | |||||
Sentinel Dubbo Adapter will automatically resolve the Dubbo consumer's *application name* as the caller's name (`origin`), | |||||
and will bring the caller's name when doing resource protection. | |||||
If `limitApp` of flow rules is not configured (`default`), flow control will take effects on all callers. | |||||
If `limitApp` of a flow rule is configured with a caller, then the corresponding flow rule will only take effect on the specific caller. | |||||
> Note: Dubbo consumer does not provide its Dubbo application name when doing RPC, | |||||
so developers should manually put the application name into *attachment* at consumer side, | |||||
then extract it at provider side. Sentinel Dubbo Adapter has implemented a filter (`DubboAppContextFilter`) | |||||
where consumer can carry application name information to provider automatically. | |||||
If the consumer does not use Sentinel Dubbo Adapter but requires flow control based on caller, developers can manually put the application name into attachment with the key `dubboApplication`. | |||||
## Global fallback | |||||
Sentinel Dubbo Adapter supports global fallback configuration. | |||||
The global fallback will handle exceptions and give replacement result when blocked by | |||||
flow control, degrade or system load protection. You can implement your own `DubboFallback` interface | |||||
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/en-us/docs/user/demos/local-mock.html) to provide fallback implementation of degraded Dubbo services. |
@@ -0,0 +1,50 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
<parent> | |||||
<artifactId>sentinel-adapter</artifactId> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<version>1.5.1-SNAPSHOT</version> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>sentinel-apache-dubbo-adapter</artifactId> | |||||
<packaging>jar</packaging> | |||||
<properties> | |||||
<java.source.version>1.8</java.source.version> | |||||
<java.target.version>1.8</java.target.version> | |||||
<apache.dubbo.version>2.7.1</apache.dubbo.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.alibaba.csp</groupId> | |||||
<artifactId>sentinel-core</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.dubbo</groupId> | |||||
<artifactId>dubbo</artifactId> | |||||
<version>${apache.dubbo.version}</version> | |||||
<scope>provided</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>junit</groupId> | |||||
<artifactId>junit</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.mockito</groupId> | |||||
<artifactId>mockito-core</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.alibaba</groupId> | |||||
<artifactId>fastjson</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
</dependencies> | |||||
</project> |
@@ -0,0 +1,43 @@ | |||||
/* | |||||
* 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 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. | |||||
* | |||||
* @author Eric Zhao | |||||
*/ | |||||
@Activate(group = "consumer") | |||||
public class DubboAppContextFilter implements Filter { | |||||
@Override | |||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | |||||
String application = invoker.getUrl().getParameter(Constants.APPLICATION_KEY); | |||||
if (application != null) { | |||||
RpcContext.getContext().setAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, application); | |||||
} | |||||
return invoker.invoke(invocation); | |||||
} | |||||
} |
@@ -0,0 +1,54 @@ | |||||
/* | |||||
* 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 org.apache.dubbo.rpc.Invocation; | |||||
import org.apache.dubbo.rpc.Invoker; | |||||
/** | |||||
* @author Eric Zhao | |||||
*/ | |||||
public final class DubboUtils { | |||||
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(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() {} | |||||
} |
@@ -0,0 +1,83 @@ | |||||
/* | |||||
* 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.Entry; | |||||
import com.alibaba.csp.sentinel.EntryType; | |||||
import com.alibaba.csp.sentinel.SphU; | |||||
import com.alibaba.csp.sentinel.Tracer; | |||||
import com.alibaba.csp.sentinel.log.RecordLog; | |||||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||||
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> | |||||
* | |||||
* If you want to disable the consumer filter, you can configure: | |||||
* <pre> | |||||
* <dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/> | |||||
* </pre> | |||||
* | |||||
* @author Carpenter Lee | |||||
* @author Eric Zhao | |||||
*/ | |||||
@Activate(group = "consumer") | |||||
public class SentinelDubboConsumerFilter implements Filter { | |||||
public SentinelDubboConsumerFilter() { | |||||
RecordLog.info("Sentinel Apache Dubbo consumer filter initialized"); | |||||
} | |||||
@Override | |||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | |||||
Entry interfaceEntry = null; | |||||
Entry methodEntry = null; | |||||
try { | |||||
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.traceEntry(e, interfaceEntry); | |||||
Tracer.traceEntry(e, 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(); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,93 @@ | |||||
/* | |||||
* 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.Entry; | |||||
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 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>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 Carpenter Lee | |||||
* @author Eric Zhao | |||||
*/ | |||||
@Activate(group = "provider") | |||||
public class SentinelDubboProviderFilter implements Filter { | |||||
public SentinelDubboProviderFilter() { | |||||
RecordLog.info("Sentinel Apache Dubbo provider filter initialized"); | |||||
} | |||||
@Override | |||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | |||||
// Get origin caller. | |||||
String application = DubboUtils.getApplication(invocation, ""); | |||||
Entry interfaceEntry = null; | |||||
Entry methodEntry = null; | |||||
try { | |||||
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()) { | |||||
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.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(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,35 @@ | |||||
/* | |||||
* 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 org.apache.dubbo.rpc.Invocation; | |||||
import org.apache.dubbo.rpc.Invoker; | |||||
import org.apache.dubbo.rpc.Result; | |||||
/** | |||||
* @author Eric Zhao | |||||
*/ | |||||
public class DefaultDubboFallback implements DubboFallback { | |||||
@Override | |||||
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex) { | |||||
// Just wrap and throw the exception. | |||||
throw new SentinelRpcException(ex); | |||||
} | |||||
} |
@@ -0,0 +1,41 @@ | |||||
/* | |||||
* 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 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 | |||||
*/ | |||||
@FunctionalInterface | |||||
public interface DubboFallback { | |||||
/** | |||||
* Handle the block exception and provide fallback result. | |||||
* | |||||
* @param invoker Dubbo invoker | |||||
* @param invocation Dubbo invocation | |||||
* @param ex block exception | |||||
* @return fallback result | |||||
*/ | |||||
Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex); | |||||
} |
@@ -0,0 +1,54 @@ | |||||
/* | |||||
* 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.util.AssertUtil; | |||||
/** | |||||
* <p>Global fallback registry for Dubbo.</p> | |||||
* | |||||
* <p> | |||||
* Note: Circuit breaking is mainly designed for consumer. The provider should not | |||||
* give fallback result in most circumstances. | |||||
* </p> | |||||
* | |||||
* @author Eric Zhao | |||||
*/ | |||||
public final class DubboFallbackRegistry { | |||||
private static volatile DubboFallback consumerFallback = new DefaultDubboFallback(); | |||||
private static volatile DubboFallback providerFallback = new DefaultDubboFallback(); | |||||
public static DubboFallback getConsumerFallback() { | |||||
return consumerFallback; | |||||
} | |||||
public static void setConsumerFallback(DubboFallback consumerFallback) { | |||||
AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null"); | |||||
DubboFallbackRegistry.consumerFallback = consumerFallback; | |||||
} | |||||
public static DubboFallback getProviderFallback() { | |||||
return providerFallback; | |||||
} | |||||
public static void setProviderFallback(DubboFallback providerFallback) { | |||||
AssertUtil.notNull(providerFallback, "providerFallback cannot be null"); | |||||
DubboFallbackRegistry.providerFallback = providerFallback; | |||||
} | |||||
private DubboFallbackRegistry() {} | |||||
} |
@@ -0,0 +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 |
@@ -0,0 +1,40 @@ | |||||
/* | |||||
* 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.slots.clusterbuilder.ClusterBuilderSlot; | |||||
import org.apache.dubbo.rpc.RpcContext; | |||||
/** | |||||
* 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 cdfive | |||||
*/ | |||||
public class BaseTest { | |||||
/** | |||||
* Clean up resources for context, clusterNodeMap, processorSlotChainMap | |||||
*/ | |||||
protected static void cleanUpAll() { | |||||
RpcContext.removeContext(); | |||||
ClusterBuilderSlot.getClusterNodeMap().clear(); | |||||
CtSph.resetChainMap(); | |||||
} | |||||
} |
@@ -0,0 +1,75 @@ | |||||
/* | |||||
* 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 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.*; | |||||
import static org.mockito.Mockito.*; | |||||
/** | |||||
* @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); | |||||
} | |||||
} |
@@ -0,0 +1,75 @@ | |||||
/* | |||||
* 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 org.apache.dubbo.rpc.Invocation; | |||||
import org.apache.dubbo.rpc.Invoker; | |||||
import org.junit.Test; | |||||
import java.lang.reflect.Method; | |||||
import java.util.HashMap; | |||||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; | |||||
import static org.junit.Assert.assertEquals; | |||||
import static org.junit.Assert.fail; | |||||
import static org.mockito.Mockito.*; | |||||
/** | |||||
* @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); | |||||
} | |||||
} |
@@ -0,0 +1,142 @@ | |||||
/* | |||||
* 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.Constants; | |||||
import com.alibaba.csp.sentinel.Entry; | |||||
import com.alibaba.csp.sentinel.EntryType; | |||||
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 java.lang.reflect.Method; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
import static org.junit.Assert.*; | |||||
import static org.mockito.Mockito.*; | |||||
/** | |||||
* @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()); | |||||
} | |||||
} |
@@ -0,0 +1,145 @@ | |||||
/* | |||||
* 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.Entry; | |||||
import com.alibaba.csp.sentinel.EntryType; | |||||
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 java.lang.reflect.Method; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
import static org.junit.Assert.*; | |||||
import static org.mockito.Mockito.*; | |||||
/** | |||||
* @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)); | |||||
} | |||||
} |
@@ -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()); | |||||
} | |||||
} |
@@ -0,0 +1,23 @@ | |||||
/* | |||||
* 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.provider; | |||||
/** | |||||
* @author leyou | |||||
*/ | |||||
public interface DemoService { | |||||
String sayHello(String name, int n); | |||||
} |
@@ -0,0 +1,27 @@ | |||||
/* | |||||
* 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.provider.impl; | |||||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; | |||||
/** | |||||
* @author leyou | |||||
*/ | |||||
public class DemoServiceImpl implements DemoService { | |||||
public String sayHello(String name, int n) { | |||||
return "Hello " + name + ", " + n; | |||||
} | |||||
} |
@@ -0,0 +1,18 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<beans xmlns="http://www.springframework.org/schema/beans" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" | |||||
xsi:schemaLocation="http://www.springframework.org/schema/beans | |||||
http://www.springframework.org/schema/beans/spring-beans.xsd | |||||
http://code.alibabatech.com/schema/dubbo | |||||
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> | |||||
<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.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.provider.DemoService"/> | |||||
</beans> |
@@ -0,0 +1,18 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<beans xmlns="http://www.springframework.org/schema/beans" | |||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" | |||||
xsi:schemaLocation="http://www.springframework.org/schema/beans | |||||
http://www.springframework.org/schema/beans/spring-beans.xsd | |||||
http://code.alibabatech.com/schema/dubbo | |||||
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> | |||||
<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.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.provider.DemoService"/> | |||||
</beans> |
@@ -3,7 +3,10 @@ | |||||
> 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/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6%E7%9A%84%E9%80%82%E9%85%8D#dubbo)。 | ||||
Sentinel Dubbo Adapter provides service consumer filter and provider filter | Sentinel Dubbo Adapter provides service consumer filter and provider filter | ||||
for [Dubbo](http://dubbo.io/) services. | |||||
for [Dubbo](https://dubbo.apache.org/en-us/) services. | |||||
**Note: This adapter only supports legacy Dubbo 2.6.x version and below.** | |||||
For new Apache Dubbo 2.7.x or above version, please use `sentinel-apache-dubbo-adapter` module instead. | |||||
To use Sentinel Dubbo Adapter, you can simply add the following dependency to your `pom.xml`: | To use Sentinel Dubbo Adapter, you can simply add the following dependency to your `pom.xml`: | ||||
@@ -28,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"/> | <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 | ## Dubbo resources | ||||
@@ -62,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` | and then register to `DubboFallbackRegistry`. If no fallback is configured, Sentinel will wrap the `BlockException` | ||||
then directly throw it out. | 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. | |||||
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. |