This commit is contained in:
shuhongfan
2023-09-04 16:40:17 +08:00
commit cf5ac25c14
8267 changed files with 1305066 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
# Sentinel Dubbo Adapter
> Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/主流框架的适配#dubbo)。
Sentinel Dubbo Adapter provides service consumer filter and provider filter
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`:
```xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-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 interfaceresourceName format is `interfaceName`e.g. `com.alibaba.csp.sentinel.demo.dubbo.FooService`
- Service methodresourceName 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`.
>
> Since 1.8.0, the adapter provides support for customizing origin parsing logic. You may register your own `DubboOriginParser`
> implementation to `DubboAdapterGlobalConfig`.
## 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 `DubboAdapterGlobalConfig`.
If no fallback is configured, Sentinel will wrap the `BlockException` as the fallback result.
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.

View File

@@ -0,0 +1,48 @@
<?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>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-adapter</artifactId>
<version>1.8.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sentinel-dubbo-adapter</artifactId>
<packaging>jar</packaging>
<properties>
<dubbo.version>2.6.6</dubbo.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${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>

View File

@@ -0,0 +1,66 @@
/*
* 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.util.StringUtil;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
/**
* @author leyou
*/
abstract class AbstractDubboFilter implements Filter {
protected String getMethodResourceName(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();
}
protected String getMethodResourceName(Invoker<?> invoker, Invocation invocation, String prefix) {
if (StringUtil.isBlank(prefix)) {
return getMethodResourceName(invoker, invocation);
}
StringBuilder buf = new StringBuilder(64);
return buf.append(prefix)
.append(getMethodResourceName(invoker, invocation))
.toString();
}
protected String getInterfaceName(Invoker<?> invoker) {
return invoker.getInterface().getName();
}
protected String getInterfaceName(Invoker<?> invoker, String prefix) {
if (StringUtil.isBlank(prefix)) {
return getInterfaceName(invoker);
}
return prefix + getInterfaceName(invoker);
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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.adapter.dubbo.fallback.DefaultDubboFallback;
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallback;
import com.alibaba.csp.sentinel.adapter.dubbo.origin.DefaultDubboOriginParser;
import com.alibaba.csp.sentinel.adapter.dubbo.origin.DubboOriginParser;
import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
/**
* <p>Global config and callback registry of Dubbo legacy adapter.</p>
*
* @author lianglin
* @author Eric Zhao
* @since 1.7.0
*/
public final class DubboAdapterGlobalConfig {
private static final String TRUE_STR = "true";
public static final String DUBBO_RES_NAME_WITH_PREFIX_KEY = "csp.sentinel.dubbo.resource.use.prefix";
public static final String DUBBO_PROVIDER_RES_NAME_PREFIX_KEY = "csp.sentinel.dubbo.resource.provider.prefix";
public static final String DUBBO_CONSUMER_RES_NAME_PREFIX_KEY = "csp.sentinel.dubbo.resource.consumer.prefix";
private static final String DEFAULT_DUBBO_PROVIDER_PREFIX = "dubbo:provider:";
private static final String DEFAULT_DUBBO_CONSUMER_PREFIX = "dubbo:consumer:";
private static volatile DubboFallback consumerFallback = new DefaultDubboFallback();
private static volatile DubboFallback providerFallback = new DefaultDubboFallback();
private static volatile DubboOriginParser originParser = new DefaultDubboOriginParser();
public static boolean isUsePrefix() {
return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_RES_NAME_WITH_PREFIX_KEY));
}
public static String getDubboProviderPrefix() {
if (isUsePrefix()) {
String config = SentinelConfig.getConfig(DUBBO_PROVIDER_RES_NAME_PREFIX_KEY);
return StringUtil.isNotBlank(config) ? config : DEFAULT_DUBBO_PROVIDER_PREFIX;
}
return null;
}
public static String getDubboConsumerPrefix() {
if (isUsePrefix()) {
String config = SentinelConfig.getConfig(DUBBO_CONSUMER_RES_NAME_PREFIX_KEY);
return StringUtil.isNotBlank(config) ? config : DEFAULT_DUBBO_CONSUMER_PREFIX;
}
return null;
}
public static DubboFallback getConsumerFallback() {
return consumerFallback;
}
public static void setConsumerFallback(DubboFallback consumerFallback) {
AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null");
DubboAdapterGlobalConfig.consumerFallback = consumerFallback;
}
public static DubboFallback getProviderFallback() {
return providerFallback;
}
public static void setProviderFallback(DubboFallback providerFallback) {
AssertUtil.notNull(providerFallback, "providerFallback cannot be null");
DubboAdapterGlobalConfig.providerFallback = providerFallback;
}
/**
* Get the origin parser of Dubbo adapter.
*
* @return the origin parser
* @since 1.8.0
*/
public static DubboOriginParser getOriginParser() {
return originParser;
}
/**
* Set the origin parser of Dubbo adapter.
*
* @param originParser the origin parser
* @since 1.8.0
*/
public static void setOriginParser(DubboOriginParser originParser) {
AssertUtil.notNull(originParser, "originParser cannot be null");
DubboAdapterGlobalConfig.originParser = originParser;
}
private DubboAdapterGlobalConfig() {}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.dubbo;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import static com.alibaba.dubbo.common.Constants.CONSUMER;
/**
* 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.DUBBO_APPLICATION_KEY, application);
}
return invoker.invoke(invocation);
}
}

View File

@@ -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;
import com.alibaba.dubbo.rpc.Invocation;
/**
* @author Eric Zhao
*/
public final class DubboUtils {
public static final String DUBBO_APPLICATION_KEY = "dubboApplication";
public static String getApplication(Invocation invocation, String defaultValue) {
if (invocation == null || invocation.getAttachments() == null) {
throw new IllegalArgumentException("Bad invocation instance");
}
return invocation.getAttachment(DUBBO_APPLICATION_KEY, defaultValue);
}
private DubboUtils() {}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.ResourceTypeConstants;
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.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import static com.alibaba.dubbo.common.Constants.CONSUMER;
/**
* <p>Dubbo service consumer filter for Sentinel. Auto activated by default.</p>
*
* If you want to disable the consumer filter, you can configure:
* <pre>
* &lt;dubbo:consumer filter="-sentinel.dubbo.consumer.filter"/&gt;
* </pre>
*
* @author leyou
* @author Eric Zhao
*/
@Activate(group = CONSUMER)
public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements Filter {
public SentinelDubboConsumerFilter() {
RecordLog.info("Sentinel Dubbo consumer filter initialized");
}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Entry interfaceEntry = null;
Entry methodEntry = null;
try {
String prefix = DubboAdapterGlobalConfig.getDubboConsumerPrefix();
String interfaceResourceName = getInterfaceName(invoker, prefix);
String methodResourceName = getMethodResourceName(invoker, invocation, prefix);
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC,
EntryType.OUT, invocation.getArguments());
Result result = invoker.invoke(invocation);
if (result.hasException()) {
Throwable e = result.getException();
// Record common exception.
Tracer.traceEntry(e, interfaceEntry);
Tracer.traceEntry(e, methodEntry);
}
return result;
} catch (BlockException e) {
return DubboAdapterGlobalConfig.getConsumerFallback().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();
}
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* 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.ResourceTypeConstants;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.log.RecordLog;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import static com.alibaba.dubbo.common.Constants.PROVIDER;
/**
* <p>Dubbo service provider filter for Sentinel. Auto activated by default.</p>
*
* If you want to disable the provider filter, you can configure:
* <pre>
* &lt;dubbo:provider filter="-sentinel.dubbo.provider.filter"/&gt;
* </pre>
*
* @author leyou
* @author Eric Zhao
*/
@Activate(group = PROVIDER)
public class SentinelDubboProviderFilter extends AbstractDubboFilter implements Filter {
public SentinelDubboProviderFilter() {
RecordLog.info("Sentinel Dubbo provider filter initialized");
}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// Get origin caller.
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(invoker, invocation);
if (null == origin) {
origin = "";
}
Entry interfaceEntry = null;
Entry methodEntry = null;
try {
String prefix = DubboAdapterGlobalConfig.getDubboProviderPrefix();
String methodResourceName = getMethodResourceName(invoker, invocation, prefix);
String interfaceName = getInterfaceName(invoker, prefix);
ContextUtil.enter(methodResourceName, origin);
interfaceEntry = SphU.entry(interfaceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN);
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC,
EntryType.IN, 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 DubboAdapterGlobalConfig.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();
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcResult;
/**
* @author Eric Zhao
*/
public class DefaultDubboFallback implements DubboFallback {
@Override
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex) {
// Just wrap the exception. edit by wzg923 2020/9/23
RpcResult result = new RpcResult();
result.setException(new SentinelRpcException(ex.toRuntimeException()));
return result;
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
/**
* Fallback handler for Dubbo services.
*
* @author Eric Zhao
*/
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);
}

View File

@@ -0,0 +1,46 @@
/*
* 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.adapter.dubbo.DubboAdapterGlobalConfig;
/**
* <p>Global fallback registry for Dubbo.</p>
*
* @author Eric Zhao
* @deprecated use {@link DubboAdapterGlobalConfig} instead.
*/
@Deprecated
public final class DubboFallbackRegistry {
public static DubboFallback getConsumerFallback() {
return DubboAdapterGlobalConfig.getConsumerFallback();
}
public static void setConsumerFallback(DubboFallback consumerFallback) {
DubboAdapterGlobalConfig.setConsumerFallback(consumerFallback);
}
public static DubboFallback getProviderFallback() {
return DubboAdapterGlobalConfig.getProviderFallback();
}
public static void setProviderFallback(DubboFallback providerFallback) {
DubboAdapterGlobalConfig.setProviderFallback(providerFallback);
}
private DubboFallbackRegistry() {}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 1999-2020 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
*
* https://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.origin;
import com.alibaba.csp.sentinel.adapter.dubbo.DubboUtils;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
/**
* Default Dubbo origin parser.
*
* @author tiecheng
* @since 1.8.0
*/
public class DefaultDubboOriginParser implements DubboOriginParser {
@Override
public String parse(Invoker<?> invoker, Invocation invocation) {
return DubboUtils.getApplication(invocation, "");
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 1999-2020 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
*
* https://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.origin;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
/**
* Customized origin parser for Dubbo provider filter.
*
* @author tiecheng
* @since 1.8.0
*/
public interface DubboOriginParser {
/**
* Parses the origin (caller) from Dubbo invocation.
*
* @param invoker Dubbo invoker
* @param invocation Dubbo invocation
* @return the parsed origin
*/
String parse(Invoker<?> invoker, Invocation invocation);
}

View File

@@ -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

View File

@@ -0,0 +1,24 @@
package com.alibaba.csp.sentinel;
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
import com.alibaba.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();
}
}

View File

@@ -0,0 +1,89 @@
package com.alibaba.csp.sentinel.adapter.dubbo;
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService;
import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Method;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* @author cdfive
*/
public class AbstractDubboFilterTest {
@Before
public void setUp() {
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "true");
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_PROVIDER_RES_NAME_PREFIX_KEY, "");
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_CONSUMER_RES_NAME_PREFIX_KEY, "");
}
@After
public void tearDown() {
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "false");
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_PROVIDER_RES_NAME_PREFIX_KEY, "");
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_CONSUMER_RES_NAME_PREFIX_KEY, "");
}
private AbstractDubboFilter filter = new AbstractDubboFilter() {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
return null;
}
};
@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 = filter.getMethodResourceName(invoker, invocation);
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName);
}
@Test
public void testGetResourceNameWithPrefix() {
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());
//test with default prefix
String resourceName = filter.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboProviderPrefix());
System.out.println("resourceName = " + resourceName);
assertEquals("dubbo:provider:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName);
resourceName = filter.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboConsumerPrefix());
assertEquals("dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName);
//test with custom prefix
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_PROVIDER_RES_NAME_PREFIX_KEY, "my:dubbo:provider:");
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_CONSUMER_RES_NAME_PREFIX_KEY, "my:dubbo:consumer:");
resourceName = filter.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboProviderPrefix());
assertEquals("my:dubbo:provider:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName);
resourceName = filter.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboConsumerPrefix());
assertEquals("my:dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName);
}
}

View File

@@ -0,0 +1,59 @@
package com.alibaba.csp.sentinel.adapter.dubbo;
import com.alibaba.csp.sentinel.BaseTest;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.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.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.DUBBO_APPLICATION_KEY);
assertNull(application);
}
}

View File

@@ -0,0 +1,39 @@
package com.alibaba.csp.sentinel.adapter.dubbo;
import com.alibaba.dubbo.rpc.Invocation;
import org.junit.Test;
import java.util.HashMap;
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<String, String>());
when(invocation.getAttachment(DubboUtils.DUBBO_APPLICATION_KEY, "")).thenReturn("consumerA");
String application = DubboUtils.getApplication(invocation, "");
verify(invocation).getAttachment(DubboUtils.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.DUBBO_APPLICATION_KEY, "")).thenReturn("consumerA");
DubboUtils.getApplication(invocation, "");
fail("No attachments in invocation, IllegalArgumentException should be thrown!");
}
}

View File

@@ -0,0 +1,131 @@
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 com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
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(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
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 = filter.getMethodResourceName(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.getEntryType());
// 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.getEntryType());
// 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.getEntryType());
// 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());
}
}

View File

@@ -0,0 +1,133 @@
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 com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
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.DUBBO_APPLICATION_KEY, "")).thenReturn(originApplication);
final Result result = mock(Result.class);
when(result.hasException()).thenReturn(false);
when(invoker.invoke(invocation)).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
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 = filter.getMethodResourceName(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.getEntryType());
// 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.getEntryType());
// 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.getEntryType());
// 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));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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.adapter.dubbo.DubboAdapterGlobalConfig;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcResult;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Eric Zhao
*/
public class DubboFallbackRegistryTest {
@Test
public void testDefaultFallback() {
// Test for default fallback.
BlockException ex = new FlowException("xxx");
Result result = new DefaultDubboFallback().handle(null, null, ex);
Assert.assertTrue(result.hasException());
Assert.assertEquals(SentinelRpcException.class, result.getException().getClass());
}
@Test
public void testCustomFallback() {
BlockException ex = new FlowException("xxx");
DubboAdapterGlobalConfig.setConsumerFallback(new DubboFallback() {
@Override
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException e) {
return new RpcResult("Error: " + e.getClass().getName());
}
});
Result result = DubboAdapterGlobalConfig.getConsumerFallback()
.handle(null, null, ex);
Assert.assertFalse("The invocation should not fail", result.hasException());
Assert.assertEquals("Error: " + ex.getClass().getName(), result.getValue());
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 1999-2020 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
*
* https://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.origin;
import com.alibaba.csp.sentinel.adapter.dubbo.DubboAdapterGlobalConfig;
import com.alibaba.csp.sentinel.adapter.dubbo.DubboUtils;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.RpcInvocation;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
/**
* @author tiecheng
*/
public class DubboOriginRegistryTest {
@After
public void cleanUp() {
DubboAdapterGlobalConfig.setOriginParser(new DefaultDubboOriginParser());
}
@Test(expected = IllegalArgumentException.class)
public void testDefaultOriginParserFail() {
DubboAdapterGlobalConfig.getOriginParser().parse(null, null);
}
@Test
public void testDefaultOriginParserSuccess() {
RpcInvocation invocation = new RpcInvocation();
String dubboName = "sentinel";
invocation.setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, dubboName);
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation);
Assert.assertEquals(dubboName, origin);
}
@Test
public void testCustomOriginParser() {
DubboAdapterGlobalConfig.setOriginParser(new DubboOriginParser() {
@Override
public String parse(Invoker<?> invoker, Invocation invocation) {
return invocation.getAttachment(DubboUtils.DUBBO_APPLICATION_KEY, "default") + "_" + invocation
.getMethodName();
}
});
RpcInvocation invocation = new RpcInvocation();
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation);
Assert.assertEquals("default_null", origin);
String dubboName = "sentinel";
invocation.setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, dubboName);
origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation);
Assert.assertEquals(dubboName + "_null", origin);
invocation.setMethodName("hello");
origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation);
Assert.assertEquals(dubboName + "_hello", origin);
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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>