* Support customized origin parser in Apache Dubbo 2.7.x adapter * 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)master
@@ -52,17 +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. |
@@ -36,7 +36,7 @@ public abstract class BaseSentinelDubboFilter implements Filter { | |||
* @param invocation | |||
* @return | |||
*/ | |||
abstract String getMethodName(Invoker invoker, Invocation invocation); | |||
abstract String getMethodName(Invoker invoker, Invocation invocation, String prefix); | |||
/** | |||
* Get interface name of dubbo rpc | |||
@@ -44,7 +44,7 @@ public abstract class BaseSentinelDubboFilter implements Filter { | |||
* @param invoker | |||
* @return | |||
*/ | |||
abstract String getInterfaceName(Invoker invoker); | |||
abstract String getInterfaceName(Invoker invoker, String prefix); | |||
} |
@@ -15,7 +15,7 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
import org.apache.dubbo.rpc.Invocation; | |||
import org.apache.dubbo.rpc.Invoker; | |||
@@ -34,11 +34,11 @@ public final class DubboUtils { | |||
return invocation.getAttachment(SENTINEL_DUBBO_APPLICATION_KEY, defaultValue); | |||
} | |||
public static String getResourceName(Invoker<?> invoker, Invocation invocation){ | |||
return getResourceName(invoker, invocation, false); | |||
public static String getMethodResourceName(Invoker<?> invoker, Invocation invocation){ | |||
return getMethodResourceName(invoker, invocation, false); | |||
} | |||
public static String getResourceName(Invoker<?> invoker, Invocation invocation, Boolean useGroupAndVersion) { | |||
public static String getMethodResourceName(Invoker<?> invoker, Invocation invocation, Boolean useGroupAndVersion) { | |||
StringBuilder buf = new StringBuilder(64); | |||
String interfaceResource = useGroupAndVersion ? invoker.getUrl().getColonSeparatedKey() : invoker.getInterface().getName(); | |||
buf.append(interfaceResource) | |||
@@ -57,23 +57,39 @@ public final class DubboUtils { | |||
return buf.toString(); | |||
} | |||
public static String getResourceName(Invoker<?> invoker, Invocation invocation, String prefix) { | |||
public static String getMethodResourceName(Invoker<?> invoker, Invocation invocation, String prefix) { | |||
if (StringUtil.isNotBlank(prefix)) { | |||
return new StringBuilder(64) | |||
.append(prefix) | |||
.append(getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled())) | |||
.append(getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboInterfaceGroupAndVersionEnabled())) | |||
.toString(); | |||
} else { | |||
return getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled()); | |||
return getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboInterfaceGroupAndVersionEnabled()); | |||
} | |||
} | |||
public static String getInterfaceName(Invoker invoker) { | |||
return DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey() | |||
: invoker.getInterface().getName(); | |||
return getInterfaceName(invoker, false); | |||
} | |||
public static String getInterfaceName(Invoker<?> invoker, Boolean useGroupAndVersion) { | |||
StringBuilder buf = new StringBuilder(64); | |||
return useGroupAndVersion ? invoker.getUrl().getColonSeparatedKey() : invoker.getInterface().getName(); | |||
} | |||
public static String getInterfaceName(Invoker<?> invoker, String prefix) { | |||
if (StringUtil.isNotBlank(prefix)) { | |||
return new StringBuilder(64) | |||
.append(prefix) | |||
.append(getInterfaceName(invoker, DubboAdapterGlobalConfig.getDubboInterfaceGroupAndVersionEnabled())) | |||
.toString(); | |||
} else { | |||
return getInterfaceName(invoker, DubboAdapterGlobalConfig.getDubboInterfaceGroupAndVersionEnabled()); | |||
} | |||
} | |||
private DubboUtils() { | |||
} | |||
} |
@@ -15,21 +15,12 @@ | |||
*/ | |||
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.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.*; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
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.Invocation; | |||
import org.apache.dubbo.rpc.InvokeMode; | |||
import org.apache.dubbo.rpc.Invoker; | |||
import org.apache.dubbo.rpc.Result; | |||
import org.apache.dubbo.rpc.RpcException; | |||
import org.apache.dubbo.rpc.*; | |||
import org.apache.dubbo.rpc.support.RpcUtils; | |||
import java.util.LinkedList; | |||
@@ -56,13 +47,13 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||
} | |||
@Override | |||
String getMethodName(Invoker invoker, Invocation invocation) { | |||
return DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); | |||
String getMethodName(Invoker invoker, Invocation invocation, String prefix) { | |||
return DubboUtils.getMethodResourceName(invoker, invocation, prefix); | |||
} | |||
@Override | |||
String getInterfaceName(Invoker invoker) { | |||
return DubboUtils.getInterfaceName(invoker); | |||
String getInterfaceName(Invoker invoker, String prefix) { | |||
return DubboUtils.getInterfaceName(invoker, prefix); | |||
} | |||
@Override | |||
@@ -79,8 +70,9 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||
private Result syncInvoke(Invoker<?> invoker, Invocation invocation) { | |||
Entry interfaceEntry = null; | |||
Entry methodEntry = null; | |||
String methodResourceName = getMethodName(invoker, invocation); | |||
String interfaceResourceName = getInterfaceName(invoker); | |||
String prefix = DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey(); | |||
String interfaceResourceName = getInterfaceName(invoker, prefix); | |||
String methodResourceName = getMethodName(invoker, invocation, prefix); | |||
try { | |||
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); | |||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); | |||
@@ -91,7 +83,7 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||
} | |||
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); | |||
@@ -109,8 +101,9 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||
private Result asyncInvoke(Invoker<?> invoker, Invocation invocation) { | |||
LinkedList<EntryHolder> queue = new LinkedList<>(); | |||
String methodResourceName = getMethodName(invoker, invocation); | |||
String interfaceResourceName = getInterfaceName(invoker); | |||
String prefix = DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey(); | |||
String interfaceResourceName = getInterfaceName(invoker, prefix); | |||
String methodResourceName = getMethodName(invoker, invocation, prefix); | |||
try { | |||
queue.push(new EntryHolder(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT), null)); | |||
queue.push(new EntryHolder(SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments()), invocation.getArguments())); | |||
@@ -130,7 +123,7 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||
while (!queue.isEmpty()) { | |||
exitEntry(queue.pop()); | |||
} | |||
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); | |||
return DubboAdapterGlobalConfig.getConsumerFallback().handle(invoker, invocation, e); | |||
} | |||
} | |||
@@ -15,18 +15,12 @@ | |||
*/ | |||
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.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.*; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
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; | |||
@@ -54,27 +48,31 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter { | |||
} | |||
@Override | |||
String getMethodName(Invoker invoker, Invocation invocation) { | |||
return DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); | |||
String getMethodName(Invoker invoker, Invocation invocation, String prefix) { | |||
return DubboUtils.getMethodResourceName(invoker, invocation, prefix); | |||
} | |||
@Override | |||
String getInterfaceName(Invoker invoker) { | |||
return DubboUtils.getInterfaceName(invoker); | |||
String getInterfaceName(Invoker invoker, String prefix) { | |||
return DubboUtils.getInterfaceName(invoker, prefix); | |||
} | |||
@Override | |||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | |||
// Get origin caller. | |||
String application = DubboUtils.getApplication(invocation, ""); | |||
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(invoker, invocation); | |||
if (null == origin) { | |||
origin = ""; | |||
} | |||
Entry interfaceEntry = null; | |||
Entry methodEntry = null; | |||
String methodResourceName = getMethodName(invoker, invocation); | |||
String interfaceResourceName = getInterfaceName(invoker); | |||
String prefix = DubboAdapterGlobalConfig.getDubboProviderResNamePrefixKey(); | |||
String interfaceResourceName = getInterfaceName(invoker, prefix); | |||
String methodResourceName = getMethodName(invoker, invocation, prefix); | |||
try { | |||
// 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(methodResourceName, application); | |||
ContextUtil.enter(methodResourceName, origin); | |||
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN); | |||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments()); | |||
Result result = invoker.invoke(invocation); | |||
@@ -84,7 +82,7 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter { | |||
} | |||
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); | |||
@@ -0,0 +1,128 @@ | |||
/* | |||
* 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.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> | |||
* Responsible for dubbo service provider, consumer attribute configuration | |||
* </p> | |||
* | |||
* @author lianglin | |||
* @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:"; | |||
public static final String DUBBO_INTERFACE_GROUP_VERSION_ENABLED = "csp.sentinel.dubbo.interface.group.version.enabled"; | |||
public static final String TRACE_BIZ_EXCEPTION_ENABLED = "csp.sentinel.dubbo.trace.biz.exception.enabled"; | |||
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 getDubboProviderResNamePrefixKey() { | |||
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 getDubboConsumerResNamePrefixKey() { | |||
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 Boolean getDubboInterfaceGroupAndVersionEnabled() { | |||
return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED)); | |||
} | |||
public static Boolean getDubboBizExceptionTraceEnabled() { | |||
String traceBizExceptionEnabled = SentinelConfig.getConfig(TRACE_BIZ_EXCEPTION_ENABLED); | |||
if (StringUtil.isNotBlank(traceBizExceptionEnabled)) { | |||
return TRUE_STR.equalsIgnoreCase(traceBizExceptionEnabled); | |||
} | |||
return true; | |||
} | |||
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() {} | |||
} |
@@ -1,77 +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 final String DUBBO_INTERFACE_GROUP_VERSION_ENABLED = "csp.sentinel.dubbo.interface.group.version.enabled"; | |||
public static final String TRACE_BIZ_EXCEPTION_ENABLED = "csp.sentinel.dubbo.trace.biz.exception.enabled"; | |||
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; | |||
} | |||
public static Boolean getDubboInterfaceGroupAndVersionEnabled() { | |||
return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED)); | |||
} | |||
public static Boolean getDubboBizExceptionTraceEnabled() { | |||
String traceBizExceptionEnabled = SentinelConfig.getConfig(TRACE_BIZ_EXCEPTION_ENABLED); | |||
if (StringUtil.isNotBlank(traceBizExceptionEnabled)) { | |||
return TRUE_STR.equalsIgnoreCase(traceBizExceptionEnabled); | |||
} | |||
return true; | |||
} | |||
} |
@@ -17,7 +17,7 @@ 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.AsyncRpcResult; | |||
import org.apache.dubbo.rpc.Invocation; | |||
import org.apache.dubbo.rpc.Invoker; | |||
import org.apache.dubbo.rpc.Result; | |||
@@ -29,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 AsyncRpcResult.newDefaultAsyncResult(null, new SentinelRpcException(ex), invocation); | |||
} | |||
} |
@@ -15,6 +15,7 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo.fallback; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.util.AssertUtil; | |||
/** | |||
@@ -29,25 +30,22 @@ import com.alibaba.csp.sentinel.util.AssertUtil; | |||
*/ | |||
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) { | |||
AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null"); | |||
DubboFallbackRegistry.consumerFallback = consumerFallback; | |||
DubboAdapterGlobalConfig.setConsumerFallback(consumerFallback); | |||
} | |||
public static DubboFallback getProviderFallback() { | |||
return providerFallback; | |||
return DubboAdapterGlobalConfig.getProviderFallback(); | |||
} | |||
public static void setProviderFallback(DubboFallback providerFallback) { | |||
AssertUtil.notNull(providerFallback, "providerFallback cannot be null"); | |||
DubboFallbackRegistry.providerFallback = providerFallback; | |||
DubboAdapterGlobalConfig.setProviderFallback(providerFallback); | |||
} | |||
private DubboFallbackRegistry() {} | |||
@@ -0,0 +1,34 @@ | |||
/* | |||
* 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 org.apache.dubbo.rpc.Invocation; | |||
import org.apache.dubbo.rpc.Invoker; | |||
/** | |||
* Default Dubbo origin parser. | |||
* | |||
* @author jingzian | |||
*/ | |||
public class DefaultDubboOriginParser implements DubboOriginParser { | |||
@Override | |||
public String parse(Invoker<?> invoker, Invocation invocation) { | |||
return DubboUtils.getApplication(invocation, ""); | |||
} | |||
} |
@@ -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.csp.sentinel.context.Context; | |||
import org.apache.dubbo.rpc.Invocation; | |||
import org.apache.dubbo.rpc.Invoker; | |||
/** | |||
* Customized origin parser for Dubbo provider filter.{@link Context#getOrigin()} | |||
* | |||
* @author jingzian | |||
*/ | |||
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); | |||
} |
@@ -15,9 +15,8 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DefaultDubboFallback; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.config.SentinelConfig; | |||
import com.alibaba.csp.sentinel.context.ContextUtil; | |||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | |||
@@ -66,10 +65,10 @@ public class BaseTest { | |||
private void clearDubboContext() { | |||
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "false"); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_PROVIDER_PREFIX, ""); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, ""); | |||
SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | |||
DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); | |||
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_PROVIDER_RES_NAME_PREFIX_KEY, ""); | |||
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_CONSUMER_RES_NAME_PREFIX_KEY, ""); | |||
SentinelConfig.setConfig(DubboAdapterGlobalConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | |||
DubboAdapterGlobalConfig.setConsumerFallback(new DefaultDubboFallback()); | |||
RpcContext.removeContext(); | |||
} |
@@ -15,7 +15,7 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService; | |||
import com.alibaba.csp.sentinel.config.SentinelConfig; | |||
import org.apache.dubbo.common.URL; | |||
@@ -29,7 +29,7 @@ import org.junit.Test; | |||
import java.lang.reflect.Method; | |||
import java.util.HashMap; | |||
import static com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED; | |||
import static com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.fail; | |||
import static org.mockito.Mockito.*; | |||
@@ -42,8 +42,8 @@ public class DubboUtilsTest { | |||
@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, ""); | |||
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | |||
} | |||
@@ -51,8 +51,8 @@ public class DubboUtilsTest { | |||
@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, ""); | |||
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | |||
} | |||
@@ -92,7 +92,7 @@ public class DubboUtilsTest { | |||
when(invocation.getMethodName()).thenReturn(method.getName()); | |||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | |||
String resourceName = DubboUtils.getResourceName(invoker, invocation); | |||
String resourceName = DubboUtils.getMethodResourceName(invoker, invocation); | |||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); | |||
@@ -113,7 +113,7 @@ public class DubboUtilsTest { | |||
when(invocation.getMethodName()).thenReturn(method.getName()); | |||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | |||
String resourceNameUseGroupAndVersion = DubboUtils.getResourceName(invoker, invocation, true); | |||
String resourceNameUseGroupAndVersion = DubboUtils.getMethodResourceName(invoker, invocation, true); | |||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:1.0.0:grp1:sayHello(java.lang.String,int)", resourceNameUseGroupAndVersion); | |||
} | |||
@@ -130,18 +130,18 @@ public class DubboUtilsTest { | |||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | |||
//test with default prefix | |||
String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix()); | |||
String resourceName = DubboUtils.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboProviderResNamePrefixKey()); | |||
assertEquals("dubbo:provider:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); | |||
resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); | |||
resourceName = DubboUtils.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey()); | |||
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 = DubboUtils.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 = DubboUtils.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboProviderResNamePrefixKey()); | |||
assertEquals("my:dubbo:provider:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); | |||
resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()); | |||
resourceName = DubboUtils.getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey()); | |||
assertEquals("my:dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); | |||
} | |||
@@ -160,8 +160,48 @@ public class DubboUtilsTest { | |||
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | |||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", DubboUtils.getInterfaceName(invoker)); | |||
} | |||
@Test | |||
public void testGetInterfaceNameWithGroupAndVersion() throws NoSuchMethodException { | |||
URL url = URL.valueOf("dubbo://127.0.0.1:2181") | |||
.addParameter(CommonConstants.VERSION_KEY, "1.0.0") | |||
.addParameter(CommonConstants.GROUP_KEY, "grp1") | |||
.addParameter(CommonConstants.INTERFACE_KEY, DemoService.class.getName()); | |||
Invoker invoker = mock(Invoker.class); | |||
when(invoker.getUrl()).thenReturn(url); | |||
when(invoker.getInterface()).thenReturn(DemoService.class); | |||
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "true"); | |||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:1.0.0:grp1", DubboUtils.getInterfaceName(invoker)); | |||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:1.0.0:grp1", DubboUtils.getInterfaceName(invoker, true)); | |||
} | |||
@Test | |||
public void testGetInterfaceNameWithPrefix() throws NoSuchMethodException { | |||
URL url = URL.valueOf("dubbo://127.0.0.1:2181") | |||
.addParameter(CommonConstants.VERSION_KEY, "1.0.0") | |||
.addParameter(CommonConstants.GROUP_KEY, "grp1") | |||
.addParameter(CommonConstants.INTERFACE_KEY, DemoService.class.getName()); | |||
Invoker invoker = mock(Invoker.class); | |||
when(invoker.getUrl()).thenReturn(url); | |||
when(invoker.getInterface()).thenReturn(DemoService.class); | |||
//test with default prefix | |||
String resourceName = DubboUtils.getInterfaceName(invoker, DubboAdapterGlobalConfig.getDubboProviderResNamePrefixKey()); | |||
assertEquals("dubbo:provider:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", resourceName); | |||
resourceName = DubboUtils.getInterfaceName(invoker, DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey()); | |||
assertEquals("dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", 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 = DubboUtils.getInterfaceName(invoker, DubboAdapterGlobalConfig.getDubboProviderResNamePrefixKey()); | |||
assertEquals("my:dubbo:provider:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", resourceName); | |||
resourceName = DubboUtils.getInterfaceName(invoker, DubboAdapterGlobalConfig.getDubboConsumerResNamePrefixKey()); | |||
assertEquals("my:dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", resourceName); | |||
} | |||
} |
@@ -34,24 +34,13 @@ import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; | |||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||
import org.apache.dubbo.rpc.AppResponse; | |||
import org.apache.dubbo.rpc.AsyncRpcResult; | |||
import org.apache.dubbo.rpc.Invocation; | |||
import org.apache.dubbo.rpc.InvokeMode; | |||
import org.apache.dubbo.rpc.Invoker; | |||
import org.apache.dubbo.rpc.Result; | |||
import org.apache.dubbo.rpc.RpcContext; | |||
import org.apache.dubbo.rpc.*; | |||
import org.apache.dubbo.rpc.support.RpcUtils; | |||
import org.junit.After; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import java.util.ArrayList; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Queue; | |||
import java.util.Set; | |||
import java.util.*; | |||
import static com.alibaba.csp.sentinel.slots.block.RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO; | |||
import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; | |||
@@ -172,7 +161,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { | |||
Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); | |||
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); | |||
initFlowRule(consumerFilter.getMethodName(invoker, invocation)); | |||
initFlowRule(consumerFilter.getMethodName(invoker, invocation, null)); | |||
invokeDubboRpc(false, invoker, invocation); | |||
invokeDubboRpc(false, invoker, invocation); | |||
@@ -244,7 +233,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 = consumerFilter.getMethodName(invoker, invocation); | |||
String resourceName = consumerFilter.getMethodName(invoker, invocation, null); | |||
assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); | |||
assertEquals("", context.getOrigin()); | |||
@@ -297,7 +286,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 = consumerFilter.getMethodName(invoker, invocation); | |||
String resourceName = consumerFilter.getMethodName(invoker, invocation, null); | |||
assertEquals(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); | |||
assertEquals("", context.getOrigin()); | |||
@@ -344,7 +333,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { | |||
private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) { | |||
Context context = ContextUtil.getContext(); | |||
assertNull(context); | |||
String methodResourceName = consumerFilter.getMethodName(invoker, invocation); | |||
String methodResourceName = consumerFilter.getMethodName(invoker, invocation, null); | |||
Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); | |||
assertNull(entries); | |||
} | |||
@@ -102,7 +102,7 @@ public class SentinelDubboProviderFilterTest extends BaseTest { | |||
assertNotNull(context); | |||
// As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter | |||
String methodResourceName = filter.getMethodName(invoker, invocation); | |||
String methodResourceName = filter.getMethodName(invoker, invocation, null); | |||
assertEquals(methodResourceName, context.getName()); | |||
assertEquals(originApplication, context.getOrigin()); | |||
@@ -117,7 +117,7 @@ public class SentinelDubboProviderFilterTest extends BaseTest { | |||
DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); | |||
ResourceWrapper interfaceResource = interfaceNode.getId(); | |||
assertEquals(filter.getInterfaceName(invoker), interfaceResource.getName()); | |||
assertEquals(filter.getInterfaceName(invoker, null), interfaceResource.getName()); | |||
assertSame(EntryType.IN, interfaceResource.getEntryType()); | |||
// As SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); | |||
@@ -15,6 +15,7 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.adapter.dubbo.fallback; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.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; | |||
@@ -40,20 +41,21 @@ public class DubboFallbackRegistryTest { | |||
DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); | |||
} | |||
@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("The invocation should not fail",result.hasException()); | |||
Assert.assertEquals(SentinelRpcException.class, result.getException().getClass()); | |||
} | |||
@Test | |||
public void testCustomFallback() { | |||
BlockException ex = new FlowException("xxx"); | |||
DubboFallbackRegistry.setConsumerFallback( | |||
DubboAdapterGlobalConfig.setConsumerFallback( | |||
(invoker, invocation, e) -> AsyncRpcResult.newDefaultAsyncResult("Error: " + e.getClass().getName(), invocation)); | |||
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()); | |||
@@ -0,0 +1,75 @@ | |||
/* | |||
* 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.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.dubbo.rpc.RpcInvocation; | |||
import org.apache.dubbo.rpc.Invocation; | |||
import org.apache.dubbo.rpc.Invoker; | |||
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.SENTINEL_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.SENTINEL_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.SENTINEL_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); | |||
} | |||
} |
@@ -15,20 +15,17 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.demo.apache.dubbo; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.demo.apache.dubbo.consumer.ConsumerConfiguration; | |||
import com.alibaba.csp.sentinel.demo.apache.dubbo.consumer.FooServiceConsumer; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | |||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; | |||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | |||
import org.apache.dubbo.rpc.AsyncRpcResult; | |||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
@@ -125,18 +122,18 @@ public class FooConsumerBootstrap { | |||
} | |||
public static void registryCustomFallback() { | |||
DubboFallbackRegistry.setConsumerFallback( | |||
DubboAdapterGlobalConfig.setConsumerFallback( | |||
(invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult("fallback", invocation)); | |||
} | |||
public static void registryCustomFallbackForCustomException() { | |||
DubboFallbackRegistry.setConsumerFallback( | |||
DubboAdapterGlobalConfig.setConsumerFallback( | |||
(invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(new RuntimeException("fallback"), invocation)); | |||
} | |||
public static void registryCustomFallbackWhenFallbackError() { | |||
DubboFallbackRegistry.setConsumerFallback( | |||
DubboAdapterGlobalConfig.setConsumerFallback( | |||
(invoker, invocation, ex) -> { | |||
throw new RuntimeException("fallback"); | |||
}); | |||
@@ -15,7 +15,7 @@ | |||
*/ | |||
package com.alibaba.csp.sentinel.demo.apache.dubbo; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||
import com.alibaba.csp.sentinel.demo.apache.dubbo.consumer.ConsumerConfiguration; | |||
import com.alibaba.csp.sentinel.demo.apache.dubbo.consumer.FooServiceConsumer; | |||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | |||
@@ -102,7 +102,7 @@ public class FooConsumerExceptionDegradeBootstrap { | |||
} | |||
public static void registryCustomFallback() { | |||
DubboFallbackRegistry.setConsumerFallback( | |||
DubboAdapterGlobalConfig.setConsumerFallback( | |||
(invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult("fallback", invocation)); | |||
} | |||