- 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> | |||
<module>sentinel-web-servlet</module> | |||
<module>sentinel-dubbo-adapter</module> | |||
<module>sentinel-apache-dubbo-adapter</module> | |||
<module>sentinel-grpc-adapter</module> | |||
<module>sentinel-zuul-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)。 | |||
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`: | |||
@@ -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"/> | |||
``` | |||
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 | |||
@@ -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` | |||
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. |