* Unify Dubbo callback registry (for fallback and origin parser) into DubboAdapterGlobalConfig * Polish default fallback implementation (wrap exception with RpcResult rather than directly throw it out) Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -1,6 +1,6 @@ | |||
# Sentinel Dubbo Adapter | |||
> Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6%E7%9A%84%E9%80%82%E9%85%8D#dubbo)。 | |||
> Note: 中文文档请见[此处](https://github.com/alibaba/Sentinel/wiki/主流框架的适配#dubbo)。 | |||
Sentinel Dubbo Adapter provides service consumer filter and provider filter | |||
for [Dubbo](https://dubbo.apache.org/en-us/) services. | |||
@@ -52,23 +52,21 @@ If `limitApp` of flow rules is not configured (`default`), flow control will tak | |||
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`. | |||
> 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 `DubboFallbackRegistry`. If no fallback is configured, Sentinel will wrap the `BlockException` | |||
then directly throw it out. | |||
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. | |||
## Global dubbo provider origin parse | |||
Sentinel Dubbo Adapter supports global origin parse for provider. | |||
You can implement your own `DubboOriginParser` interface | |||
and then register to `DubboOriginParserRegistry`. If no originParse is configured, Sentinel will user dubbo url property application. | |||
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. |
@@ -25,12 +25,12 @@ import com.alibaba.dubbo.rpc.Invoker; | |||
*/ | |||
abstract class AbstractDubboFilter implements Filter { | |||
protected String getResourceName(Invoker<?> invoker, Invocation invocation) { | |||
protected String getMethodResourceName(Invoker<?> invoker, Invocation invocation) { | |||
StringBuilder buf = new StringBuilder(64); | |||
buf.append(invoker.getInterface().getName()) | |||
.append(":") | |||
.append(invocation.getMethodName()) | |||
.append("("); | |||
.append(":") | |||
.append(invocation.getMethodName()) | |||
.append("("); | |||
boolean isFirst = true; | |||
for (Class<?> clazz : invocation.getParameterTypes()) { | |||
if (!isFirst) { | |||
@@ -43,15 +43,24 @@ abstract class AbstractDubboFilter implements Filter { | |||
return buf.toString(); | |||
} | |||
protected String getResourceName(Invoker<?> invoker, Invocation invocation, String prefix) { | |||
protected String getMethodResourceName(Invoker<?> invoker, Invocation invocation, String prefix) { | |||
if (StringUtil.isBlank(prefix)) { | |||
return getResourceName(invoker, invocation); | |||
return getMethodResourceName(invoker, invocation); | |||
} | |||
StringBuilder buf = new StringBuilder(64); | |||
return buf.append(prefix) | |||
.append(getResourceName(invoker, invocation)) | |||
.toString(); | |||
.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); | |||
} | |||
} |
@@ -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() {} | |||
} |
@@ -20,8 +20,6 @@ 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.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.log.RecordLog; | |||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||
import com.alibaba.dubbo.common.extension.Activate; | |||
@@ -56,10 +54,12 @@ public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements | |||
Entry interfaceEntry = null; | |||
Entry methodEntry = null; | |||
try { | |||
String resourceName = getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); | |||
interfaceEntry = SphU.entry(invoker.getInterface().getName(), ResourceTypeConstants.COMMON_RPC, | |||
EntryType.OUT); | |||
methodEntry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); | |||
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()) { | |||
@@ -70,7 +70,7 @@ public class SentinelDubboConsumerFilter extends AbstractDubboFilter implements | |||
} | |||
return result; | |||
} catch (BlockException e) { | |||
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); | |||
return DubboAdapterGlobalConfig.getConsumerFallback().handle(invoker, invocation, e); | |||
} catch (RpcException e) { | |||
Tracer.traceEntry(e, interfaceEntry); | |||
Tracer.traceEntry(e, methodEntry); | |||
@@ -20,9 +20,6 @@ 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.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.origin.DubboOriginParserRegistry; | |||
import com.alibaba.csp.sentinel.context.ContextUtil; | |||
import com.alibaba.csp.sentinel.log.RecordLog; | |||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||
@@ -56,7 +53,7 @@ public class SentinelDubboProviderFilter extends AbstractDubboFilter implements | |||
@Override | |||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | |||
// Get origin caller. | |||
String origin = DubboOriginParserRegistry.getDubboOriginParser().parse(invoker, invocation); | |||
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(invoker, invocation); | |||
if (null == origin) { | |||
origin = ""; | |||
} | |||
@@ -64,11 +61,12 @@ public class SentinelDubboProviderFilter extends AbstractDubboFilter implements | |||
Entry interfaceEntry = null; | |||
Entry methodEntry = null; | |||
try { | |||
String resourceName = getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); | |||
String interfaceName = invoker.getInterface().getName(); | |||
ContextUtil.enter(resourceName, origin); | |||
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(resourceName, ResourceTypeConstants.COMMON_RPC, | |||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, | |||
EntryType.IN, invocation.getArguments()); | |||
Result result = invoker.invoke(invocation); | |||
@@ -80,7 +78,7 @@ public class SentinelDubboProviderFilter extends AbstractDubboFilter implements | |||
} | |||
return result; | |||
} catch (BlockException e) { | |||
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e); | |||
return DubboAdapterGlobalConfig.getProviderFallback().handle(invoker, invocation, e); | |||
} catch (RpcException e) { | |||
Tracer.traceEntry(e, interfaceEntry); | |||
Tracer.traceEntry(e, methodEntry); | |||
@@ -1,62 +0,0 @@ | |||
/* | |||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo.config; | |||
import com.alibaba.csp.sentinel.config.SentinelConfig; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
/** | |||
* <p> | |||
* Responsible for dubbo service provider, consumer attribute configuration | |||
* </p> | |||
* | |||
* @author lianglin | |||
* @since 1.7.0 | |||
*/ | |||
public final class DubboConfig { | |||
public static final String DUBBO_USE_PREFIX = "csp.sentinel.dubbo.resource.use.prefix"; | |||
private static final String TRUE_STR = "true"; | |||
public static final String DUBBO_PROVIDER_PREFIX = "csp.sentinel.dubbo.resource.provider.prefix"; | |||
public static final String DUBBO_CONSUMER_PREFIX = "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:"; | |||
public static boolean isUsePrefix() { | |||
return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_USE_PREFIX)); | |||
} | |||
public static String getDubboProviderPrefix() { | |||
if (isUsePrefix()) { | |||
String config = SentinelConfig.getConfig(DUBBO_PROVIDER_PREFIX); | |||
return StringUtil.isNotBlank(config) ? config : DEFAULT_DUBBO_PROVIDER_PREFIX; | |||
} | |||
return null; | |||
} | |||
public static String getDubboConsumerPrefix() { | |||
if (isUsePrefix()) { | |||
String config = SentinelConfig.getConfig(DUBBO_CONSUMER_PREFIX); | |||
return StringUtil.isNotBlank(config) ? config : DEFAULT_DUBBO_CONSUMER_PREFIX; | |||
} | |||
return null; | |||
} | |||
} |
@@ -20,6 +20,7 @@ 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 | |||
@@ -28,7 +29,7 @@ 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); | |||
// Just wrap the exception. | |||
return new RpcResult(new SentinelRpcException(ex)); | |||
} | |||
} |
@@ -15,33 +15,31 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo.fallback; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.DubboAdapterGlobalConfig; | |||
/** | |||
* Global fallback registry for Dubbo. | |||
* | |||
* Note: Degrading is mainly designed for consumer. The provider should not | |||
* give fallback result in most circumstances. | |||
* <p>Global fallback registry for Dubbo.</p> | |||
* | |||
* @author Eric Zhao | |||
* @deprecated use {@link DubboAdapterGlobalConfig} instead. | |||
*/ | |||
@Deprecated | |||
public final class DubboFallbackRegistry { | |||
private static volatile DubboFallback consumerFallback = new DefaultDubboFallback(); | |||
private static volatile DubboFallback providerFallback = new DefaultDubboFallback(); | |||
public static DubboFallback getConsumerFallback() { | |||
return consumerFallback; | |||
return DubboAdapterGlobalConfig.getConsumerFallback(); | |||
} | |||
public static void setConsumerFallback(DubboFallback consumerFallback) { | |||
DubboFallbackRegistry.consumerFallback = consumerFallback; | |||
DubboAdapterGlobalConfig.setConsumerFallback(consumerFallback); | |||
} | |||
public static DubboFallback getProviderFallback() { | |||
return providerFallback; | |||
return DubboAdapterGlobalConfig.getProviderFallback(); | |||
} | |||
public static void setProviderFallback(DubboFallback providerFallback) { | |||
DubboFallbackRegistry.providerFallback = providerFallback; | |||
DubboAdapterGlobalConfig.setProviderFallback(providerFallback); | |||
} | |||
private DubboFallbackRegistry() {} | |||
@@ -20,9 +20,10 @@ import com.alibaba.dubbo.rpc.Invocation; | |||
import com.alibaba.dubbo.rpc.Invoker; | |||
/** | |||
* Default Dubbo origin parse. | |||
* Default Dubbo origin parser. | |||
* | |||
* @author tiecheng | |||
* @since 1.8.0 | |||
*/ | |||
public class DefaultDubboOriginParser implements DubboOriginParser { | |||
@@ -15,23 +15,23 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo.origin; | |||
import com.alibaba.csp.sentinel.context.Context; | |||
import com.alibaba.dubbo.rpc.Invocation; | |||
import com.alibaba.dubbo.rpc.Invoker; | |||
/** | |||
* Customized origin parse in Dubbo provider filter. {@link Context#getOrigin()} | |||
* Customized origin parser for Dubbo provider filter. | |||
* | |||
* @author tiecheng | |||
* @since 1.8.0 | |||
*/ | |||
public interface DubboOriginParser { | |||
/** | |||
* Handle the origin parse. | |||
* Parses the origin (caller) from Dubbo invocation. | |||
* | |||
* @param invoker Dubbo invoker | |||
* @param invocation Dubbo invocation | |||
* @return parse result | |||
* @return the parsed origin | |||
*/ | |||
String parse(Invoker<?> invoker, Invocation invocation); | |||
@@ -1,37 +0,0 @@ | |||
/* | |||
* 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; | |||
/** | |||
* Global origin parser registry for Dubbo. | |||
* | |||
* @author tiecheng | |||
*/ | |||
public final class DubboOriginParserRegistry { | |||
private static volatile DubboOriginParser dubboOriginParser = new DefaultDubboOriginParser(); | |||
public static DubboOriginParser getDubboOriginParser() { | |||
return dubboOriginParser; | |||
} | |||
public static void setDubboOriginParser(DubboOriginParser dubboOriginParser) { | |||
DubboOriginParserRegistry.dubboOriginParser = dubboOriginParser; | |||
} | |||
private DubboOriginParserRegistry() {} | |||
} |
@@ -1,6 +1,5 @@ | |||
package com.alibaba.csp.sentinel.adapter.dubbo; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; | |||
import com.alibaba.csp.sentinel.config.SentinelConfig; | |||
import com.alibaba.dubbo.rpc.Invocation; | |||
@@ -26,15 +25,15 @@ public class AbstractDubboFilterTest { | |||
@Before | |||
public void setUp() { | |||
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "true"); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_PROVIDER_PREFIX, ""); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, ""); | |||
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(DubboConfig.DUBBO_PROVIDER_PREFIX, ""); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, ""); | |||
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_PROVIDER_RES_NAME_PREFIX_KEY, ""); | |||
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_CONSUMER_RES_NAME_PREFIX_KEY, ""); | |||
} | |||
private AbstractDubboFilter filter = new AbstractDubboFilter() { | |||
@@ -55,7 +54,7 @@ public class AbstractDubboFilterTest { | |||
when(invocation.getMethodName()).thenReturn(method.getName()); | |||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | |||
String resourceName = filter.getResourceName(invoker, invocation); | |||
String resourceName = filter.getMethodResourceName(invoker, invocation); | |||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); | |||
} | |||
@@ -71,19 +70,19 @@ public class AbstractDubboFilterTest { | |||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | |||
//test with default prefix | |||
String resourceName = filter.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); | |||
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.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); | |||
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(DubboConfig.DUBBO_PROVIDER_PREFIX, "my:dubbo:provider:"); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, "my:dubbo:consumer:"); | |||
resourceName = filter.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); | |||
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.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); | |||
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); | |||
} | |||
@@ -85,7 +85,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { | |||
// 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.getResourceName(invoker, invocation); | |||
String resourceName = filter.getMethodResourceName(invoker, invocation); | |||
assertEquals(Constants.CONTEXT_DEFAULT_NAME, context.getName()); | |||
assertEquals("", context.getOrigin()); | |||
@@ -85,7 +85,7 @@ public class SentinelDubboProviderFilterTest extends BaseTest { | |||
assertNotNull(context); | |||
// As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter | |||
String resourceName = filter.getResourceName(invoker, invocation); | |||
String resourceName = filter.getMethodResourceName(invoker, invocation); | |||
assertEquals(resourceName, context.getName()); | |||
assertEquals(originApplication, context.getOrigin()); | |||
@@ -15,6 +15,7 @@ | |||
*/ | |||
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; | |||
@@ -31,24 +32,25 @@ import org.junit.Test; | |||
*/ | |||
public class DubboFallbackRegistryTest { | |||
@Test(expected = SentinelRpcException.class) | |||
@Test | |||
public void testDefaultFallback() { | |||
// Test for default. | |||
// Test for default fallback. | |||
BlockException ex = new FlowException("xxx"); | |||
DubboFallbackRegistry.getConsumerFallback() | |||
.handle(null, null, ex); | |||
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"); | |||
DubboFallbackRegistry.setConsumerFallback(new DubboFallback() { | |||
DubboAdapterGlobalConfig.setConsumerFallback(new DubboFallback() { | |||
@Override | |||
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException e) { | |||
return new RpcResult("Error: " + e.getClass().getName()); | |||
} | |||
}); | |||
Result result = DubboFallbackRegistry.getConsumerFallback() | |||
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()); | |||
@@ -15,10 +15,12 @@ | |||
*/ | |||
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; | |||
@@ -30,12 +32,12 @@ public class DubboOriginRegistryTest { | |||
@After | |||
public void cleanUp() { | |||
DubboOriginParserRegistry.setDubboOriginParser(new DefaultDubboOriginParser()); | |||
DubboAdapterGlobalConfig.setOriginParser(new DefaultDubboOriginParser()); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void testDefaultOriginParserFail() { | |||
DubboOriginParserRegistry.getDubboOriginParser().parse(null, null); | |||
DubboAdapterGlobalConfig.getOriginParser().parse(null, null); | |||
} | |||
@Test | |||
@@ -43,13 +45,13 @@ public class DubboOriginRegistryTest { | |||
RpcInvocation invocation = new RpcInvocation(); | |||
String dubboName = "sentinel"; | |||
invocation.setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, dubboName); | |||
String origin = DubboOriginParserRegistry.getDubboOriginParser().parse(null, invocation); | |||
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation); | |||
Assert.assertEquals(dubboName, origin); | |||
} | |||
@Test | |||
public void testCustomOriginParser() { | |||
DubboOriginParserRegistry.setDubboOriginParser(new DubboOriginParser() { | |||
DubboAdapterGlobalConfig.setOriginParser(new DubboOriginParser() { | |||
@Override | |||
public String parse(Invoker<?> invoker, Invocation invocation) { | |||
return invocation.getAttachment(DubboUtils.DUBBO_APPLICATION_KEY, "default") + "_" + invocation | |||
@@ -58,16 +60,16 @@ public class DubboOriginRegistryTest { | |||
}); | |||
RpcInvocation invocation = new RpcInvocation(); | |||
String origin = DubboOriginParserRegistry.getDubboOriginParser().parse(null, invocation); | |||
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation); | |||
Assert.assertEquals("default_null", origin); | |||
String dubboName = "sentinel"; | |||
invocation.setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, dubboName); | |||
origin = DubboOriginParserRegistry.getDubboOriginParser().parse(null, invocation); | |||
origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation); | |||
Assert.assertEquals(dubboName + "_null", origin); | |||
invocation.setMethodName("hello"); | |||
origin = DubboOriginParserRegistry.getDubboOriginParser().parse(null, invocation); | |||
origin = DubboAdapterGlobalConfig.getOriginParser().parse(null, invocation); | |||
Assert.assertEquals(dubboName + "_hello", origin); | |||
} | |||
@@ -19,16 +19,14 @@ import java.util.Collections; | |||
import java.util.concurrent.ExecutorService; | |||
import java.util.concurrent.Executors; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory; | |||
import com.alibaba.csp.sentinel.demo.dubbo.consumer.ConsumerConfiguration; | |||
import com.alibaba.csp.sentinel.demo.dubbo.consumer.FooServiceConsumer; | |||
import com.alibaba.csp.sentinel.init.InitExecutor; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||
import com.alibaba.dubbo.rpc.Result; | |||
import com.alibaba.dubbo.rpc.RpcResult; | |||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; | |||
@@ -88,7 +86,7 @@ public class FooConsumerBootstrap { | |||
// Register fallback handler for consumer. | |||
// If you only want to handle degrading, you need to | |||
// check the type of BlockException. | |||
DubboFallbackRegistry.setConsumerFallback((a, b, ex) -> | |||
DubboAdapterGlobalConfig.setConsumerFallback((a, b, ex) -> | |||
new RpcResult("Error: " + ex.getClass().getTypeName())); | |||
} | |||
} |