* 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. | 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, | > 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 | ## Global fallback | ||||
Sentinel Dubbo Adapter supports global fallback configuration. | Sentinel Dubbo Adapter supports global fallback configuration. | ||||
The global fallback will handle exceptions and give replacement result when blocked by | 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 | 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. | 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 | * @param invocation | ||||
* @return | * @return | ||||
*/ | */ | ||||
abstract String getMethodName(Invoker invoker, Invocation invocation); | |||||
abstract String getMethodName(Invoker invoker, Invocation invocation, String prefix); | |||||
/** | /** | ||||
* Get interface name of dubbo rpc | * Get interface name of dubbo rpc | ||||
@@ -44,7 +44,7 @@ public abstract class BaseSentinelDubboFilter implements Filter { | |||||
* @param invoker | * @param invoker | ||||
* @return | * @return | ||||
*/ | */ | ||||
abstract String getInterfaceName(Invoker invoker); | |||||
abstract String getInterfaceName(Invoker invoker, String prefix); | |||||
} | } |
@@ -15,7 +15,7 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.adapter.dubbo; | 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 com.alibaba.csp.sentinel.util.StringUtil; | ||||
import org.apache.dubbo.rpc.Invocation; | import org.apache.dubbo.rpc.Invocation; | ||||
import org.apache.dubbo.rpc.Invoker; | import org.apache.dubbo.rpc.Invoker; | ||||
@@ -34,11 +34,11 @@ public final class DubboUtils { | |||||
return invocation.getAttachment(SENTINEL_DUBBO_APPLICATION_KEY, defaultValue); | 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); | StringBuilder buf = new StringBuilder(64); | ||||
String interfaceResource = useGroupAndVersion ? invoker.getUrl().getColonSeparatedKey() : invoker.getInterface().getName(); | String interfaceResource = useGroupAndVersion ? invoker.getUrl().getColonSeparatedKey() : invoker.getInterface().getName(); | ||||
buf.append(interfaceResource) | buf.append(interfaceResource) | ||||
@@ -57,23 +57,39 @@ public final class DubboUtils { | |||||
return buf.toString(); | 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)) { | if (StringUtil.isNotBlank(prefix)) { | ||||
return new StringBuilder(64) | return new StringBuilder(64) | ||||
.append(prefix) | .append(prefix) | ||||
.append(getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled())) | |||||
.append(getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboInterfaceGroupAndVersionEnabled())) | |||||
.toString(); | .toString(); | ||||
} else { | } else { | ||||
return getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled()); | |||||
return getMethodResourceName(invoker, invocation, DubboAdapterGlobalConfig.getDubboInterfaceGroupAndVersionEnabled()); | |||||
} | } | ||||
} | } | ||||
public static String getInterfaceName(Invoker invoker) { | 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() { | private DubboUtils() { | ||||
} | } | ||||
} | } |
@@ -15,21 +15,12 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.adapter.dubbo; | 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.log.RecordLog; | ||||
import com.alibaba.csp.sentinel.slots.block.BlockException; | import com.alibaba.csp.sentinel.slots.block.BlockException; | ||||
import org.apache.dubbo.common.extension.Activate; | 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 org.apache.dubbo.rpc.support.RpcUtils; | ||||
import java.util.LinkedList; | import java.util.LinkedList; | ||||
@@ -56,13 +47,13 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||||
} | } | ||||
@Override | @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 | @Override | ||||
String getInterfaceName(Invoker invoker) { | |||||
return DubboUtils.getInterfaceName(invoker); | |||||
String getInterfaceName(Invoker invoker, String prefix) { | |||||
return DubboUtils.getInterfaceName(invoker, prefix); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -79,8 +70,9 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||||
private Result syncInvoke(Invoker<?> invoker, Invocation invocation) { | private Result syncInvoke(Invoker<?> invoker, Invocation invocation) { | ||||
Entry interfaceEntry = null; | Entry interfaceEntry = null; | ||||
Entry methodEntry = 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 { | try { | ||||
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); | interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT); | ||||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); | methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments()); | ||||
@@ -91,7 +83,7 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||||
} | } | ||||
return result; | return result; | ||||
} catch (BlockException e) { | } catch (BlockException e) { | ||||
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e); | |||||
return DubboAdapterGlobalConfig.getConsumerFallback().handle(invoker, invocation, e); | |||||
} catch (RpcException e) { | } catch (RpcException e) { | ||||
Tracer.traceEntry(e, interfaceEntry); | Tracer.traceEntry(e, interfaceEntry); | ||||
Tracer.traceEntry(e, methodEntry); | Tracer.traceEntry(e, methodEntry); | ||||
@@ -109,8 +101,9 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter { | |||||
private Result asyncInvoke(Invoker<?> invoker, Invocation invocation) { | private Result asyncInvoke(Invoker<?> invoker, Invocation invocation) { | ||||
LinkedList<EntryHolder> queue = new LinkedList<>(); | 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 { | try { | ||||
queue.push(new EntryHolder(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT), null)); | 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())); | 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()) { | while (!queue.isEmpty()) { | ||||
exitEntry(queue.pop()); | 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; | 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.context.ContextUtil; | ||||
import com.alibaba.csp.sentinel.log.RecordLog; | import com.alibaba.csp.sentinel.log.RecordLog; | ||||
import com.alibaba.csp.sentinel.slots.block.BlockException; | import com.alibaba.csp.sentinel.slots.block.BlockException; | ||||
import org.apache.dubbo.common.extension.Activate; | import org.apache.dubbo.common.extension.Activate; | ||||
import org.apache.dubbo.rpc.Filter; | |||||
import org.apache.dubbo.rpc.Invocation; | import org.apache.dubbo.rpc.Invocation; | ||||
import org.apache.dubbo.rpc.Invoker; | import org.apache.dubbo.rpc.Invoker; | ||||
import org.apache.dubbo.rpc.Result; | import org.apache.dubbo.rpc.Result; | ||||
@@ -54,27 +48,31 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter { | |||||
} | } | ||||
@Override | @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 | @Override | ||||
String getInterfaceName(Invoker invoker) { | |||||
return DubboUtils.getInterfaceName(invoker); | |||||
String getInterfaceName(Invoker invoker, String prefix) { | |||||
return DubboUtils.getInterfaceName(invoker, prefix); | |||||
} | } | ||||
@Override | @Override | ||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { | ||||
// Get origin caller. | // Get origin caller. | ||||
String application = DubboUtils.getApplication(invocation, ""); | |||||
String origin = DubboAdapterGlobalConfig.getOriginParser().parse(invoker, invocation); | |||||
if (null == origin) { | |||||
origin = ""; | |||||
} | |||||
Entry interfaceEntry = null; | Entry interfaceEntry = null; | ||||
Entry methodEntry = 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 { | try { | ||||
// Only need to create entrance context at provider side, as context will take effect | // Only need to create entrance context at provider side, as context will take effect | ||||
// at entrance of invocation chain only (for inbound traffic). | // 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); | interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN); | ||||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments()); | methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments()); | ||||
Result result = invoker.invoke(invocation); | Result result = invoker.invoke(invocation); | ||||
@@ -84,7 +82,7 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter { | |||||
} | } | ||||
return result; | return result; | ||||
} catch (BlockException e) { | } catch (BlockException e) { | ||||
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e); | |||||
return DubboAdapterGlobalConfig.getProviderFallback().handle(invoker, invocation, e); | |||||
} catch (RpcException e) { | } catch (RpcException e) { | ||||
Tracer.traceEntry(e, interfaceEntry); | Tracer.traceEntry(e, interfaceEntry); | ||||
Tracer.traceEntry(e, methodEntry); | 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.BlockException; | ||||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | 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.Invocation; | ||||
import org.apache.dubbo.rpc.Invoker; | import org.apache.dubbo.rpc.Invoker; | ||||
import org.apache.dubbo.rpc.Result; | import org.apache.dubbo.rpc.Result; | ||||
@@ -29,7 +29,7 @@ public class DefaultDubboFallback implements DubboFallback { | |||||
@Override | @Override | ||||
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex) { | 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; | package com.alibaba.csp.sentinel.adapter.dubbo.fallback; | ||||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboAdapterGlobalConfig; | |||||
import com.alibaba.csp.sentinel.util.AssertUtil; | import com.alibaba.csp.sentinel.util.AssertUtil; | ||||
/** | /** | ||||
@@ -29,25 +30,22 @@ import com.alibaba.csp.sentinel.util.AssertUtil; | |||||
*/ | */ | ||||
public final class DubboFallbackRegistry { | public final class DubboFallbackRegistry { | ||||
private static volatile DubboFallback consumerFallback = new DefaultDubboFallback(); | |||||
private static volatile DubboFallback providerFallback = new DefaultDubboFallback(); | |||||
public static DubboFallback getConsumerFallback() { | public static DubboFallback getConsumerFallback() { | ||||
return consumerFallback; | |||||
return DubboAdapterGlobalConfig.getConsumerFallback(); | |||||
} | } | ||||
public static void setConsumerFallback(DubboFallback consumerFallback) { | public static void setConsumerFallback(DubboFallback consumerFallback) { | ||||
AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null"); | AssertUtil.notNull(consumerFallback, "consumerFallback cannot be null"); | ||||
DubboFallbackRegistry.consumerFallback = consumerFallback; | |||||
DubboAdapterGlobalConfig.setConsumerFallback(consumerFallback); | |||||
} | } | ||||
public static DubboFallback getProviderFallback() { | public static DubboFallback getProviderFallback() { | ||||
return providerFallback; | |||||
return DubboAdapterGlobalConfig.getProviderFallback(); | |||||
} | } | ||||
public static void setProviderFallback(DubboFallback providerFallback) { | public static void setProviderFallback(DubboFallback providerFallback) { | ||||
AssertUtil.notNull(providerFallback, "providerFallback cannot be null"); | AssertUtil.notNull(providerFallback, "providerFallback cannot be null"); | ||||
DubboFallbackRegistry.providerFallback = providerFallback; | |||||
DubboAdapterGlobalConfig.setProviderFallback(providerFallback); | |||||
} | } | ||||
private DubboFallbackRegistry() {} | 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; | 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.DefaultDubboFallback; | ||||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry; | |||||
import com.alibaba.csp.sentinel.config.SentinelConfig; | import com.alibaba.csp.sentinel.config.SentinelConfig; | ||||
import com.alibaba.csp.sentinel.context.ContextUtil; | import com.alibaba.csp.sentinel.context.ContextUtil; | ||||
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; | ||||
@@ -66,10 +65,10 @@ public class BaseTest { | |||||
private void clearDubboContext() { | private void clearDubboContext() { | ||||
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "false"); | 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(); | RpcContext.removeContext(); | ||||
} | } |
@@ -15,7 +15,7 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.adapter.dubbo; | 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.adapter.dubbo.provider.DemoService; | ||||
import com.alibaba.csp.sentinel.config.SentinelConfig; | import com.alibaba.csp.sentinel.config.SentinelConfig; | ||||
import org.apache.dubbo.common.URL; | import org.apache.dubbo.common.URL; | ||||
@@ -29,7 +29,7 @@ import org.junit.Test; | |||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
import java.util.HashMap; | 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.assertEquals; | ||||
import static org.junit.Assert.fail; | import static org.junit.Assert.fail; | ||||
import static org.mockito.Mockito.*; | import static org.mockito.Mockito.*; | ||||
@@ -42,8 +42,8 @@ public class DubboUtilsTest { | |||||
@Before | @Before | ||||
public void setUp() { | public void setUp() { | ||||
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "true"); | 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"); | SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | ||||
} | } | ||||
@@ -51,8 +51,8 @@ public class DubboUtilsTest { | |||||
@After | @After | ||||
public void tearDown() { | public void tearDown() { | ||||
SentinelConfig.setConfig("csp.sentinel.dubbo.resource.use.prefix", "false"); | 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"); | SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | ||||
} | } | ||||
@@ -92,7 +92,7 @@ public class DubboUtilsTest { | |||||
when(invocation.getMethodName()).thenReturn(method.getName()); | when(invocation.getMethodName()).thenReturn(method.getName()); | ||||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | 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); | 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.getMethodName()).thenReturn(method.getName()); | ||||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | 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); | 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()); | when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes()); | ||||
//test with default prefix | //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); | 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); | assertEquals("dubbo:consumer:com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:sayHello(java.lang.String,int)", resourceName); | ||||
//test with custom prefix | //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); | 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); | 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"); | SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false"); | ||||
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", DubboUtils.getInterfaceName(invoker)); | 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"); | 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.degrade.DegradeRuleManager; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | 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.apache.dubbo.rpc.support.RpcUtils; | ||||
import org.junit.After; | import org.junit.After; | ||||
import org.junit.Before; | import org.junit.Before; | ||||
import org.junit.Test; | 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 com.alibaba.csp.sentinel.slots.block.RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO; | ||||
import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; | import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; | ||||
@@ -172,7 +161,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { | |||||
Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); | Invoker invoker = DubboTestUtil.getDefaultMockInvoker(); | ||||
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString()); | 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); | ||||
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 | // 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 | // 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 | // 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(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); | ||||
assertEquals("", context.getOrigin()); | assertEquals("", context.getOrigin()); | ||||
@@ -297,7 +286,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { | |||||
// As not call ContextUtil.enter(resourceName, application) in SentinelDubboConsumerFilter, use default 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 | // 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 | // 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(com.alibaba.csp.sentinel.Constants.CONTEXT_DEFAULT_NAME, context.getName()); | ||||
assertEquals("", context.getOrigin()); | assertEquals("", context.getOrigin()); | ||||
@@ -344,7 +333,7 @@ public class SentinelDubboConsumerFilterTest extends BaseTest { | |||||
private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) { | private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) { | ||||
Context context = ContextUtil.getContext(); | Context context = ContextUtil.getContext(); | ||||
assertNull(context); | assertNull(context); | ||||
String methodResourceName = consumerFilter.getMethodName(invoker, invocation); | |||||
String methodResourceName = consumerFilter.getMethodName(invoker, invocation, null); | |||||
Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); | Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName); | ||||
assertNull(entries); | assertNull(entries); | ||||
} | } | ||||
@@ -102,7 +102,7 @@ public class SentinelDubboProviderFilterTest extends BaseTest { | |||||
assertNotNull(context); | assertNotNull(context); | ||||
// As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter | // 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(methodResourceName, context.getName()); | ||||
assertEquals(originApplication, context.getOrigin()); | assertEquals(originApplication, context.getOrigin()); | ||||
@@ -117,7 +117,7 @@ public class SentinelDubboProviderFilterTest extends BaseTest { | |||||
DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); | DefaultNode interfaceNode = (DefaultNode) childList.iterator().next(); | ||||
ResourceWrapper interfaceResource = interfaceNode.getId(); | ResourceWrapper interfaceResource = interfaceNode.getId(); | ||||
assertEquals(filter.getInterfaceName(invoker), interfaceResource.getName()); | |||||
assertEquals(filter.getInterfaceName(invoker, null), interfaceResource.getName()); | |||||
assertSame(EntryType.IN, interfaceResource.getEntryType()); | assertSame(EntryType.IN, interfaceResource.getEntryType()); | ||||
// As SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); | // As SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments()); | ||||
@@ -15,6 +15,7 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.adapter.dubbo.fallback; | 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.BlockException; | ||||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowException; | import com.alibaba.csp.sentinel.slots.block.flow.FlowException; | ||||
@@ -40,20 +41,21 @@ public class DubboFallbackRegistryTest { | |||||
DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); | DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback()); | ||||
} | } | ||||
@Test(expected = SentinelRpcException.class) | |||||
@Test | |||||
public void testDefaultFallback() { | public void testDefaultFallback() { | ||||
// Test for default. | |||||
// Test for default fallback. | |||||
BlockException ex = new FlowException("xxx"); | 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 | @Test | ||||
public void testCustomFallback() { | public void testCustomFallback() { | ||||
BlockException ex = new FlowException("xxx"); | BlockException ex = new FlowException("xxx"); | ||||
DubboFallbackRegistry.setConsumerFallback( | |||||
DubboAdapterGlobalConfig.setConsumerFallback( | |||||
(invoker, invocation, e) -> AsyncRpcResult.newDefaultAsyncResult("Error: " + e.getClass().getName(), invocation)); | (invoker, invocation, e) -> AsyncRpcResult.newDefaultAsyncResult("Error: " + e.getClass().getName(), invocation)); | ||||
Result result = DubboFallbackRegistry.getConsumerFallback() | |||||
Result result = DubboAdapterGlobalConfig.getConsumerFallback() | |||||
.handle(null, null, ex); | .handle(null, null, ex); | ||||
Assert.assertFalse("The invocation should not fail", result.hasException()); | Assert.assertFalse("The invocation should not fail", result.hasException()); | ||||
Assert.assertEquals("Error: " + ex.getClass().getName(), result.getValue()); | 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; | 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.ConsumerConfiguration; | ||||
import com.alibaba.csp.sentinel.demo.apache.dubbo.consumer.FooServiceConsumer; | 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.RuleConstant; | ||||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | 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.FlowRule; | ||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | ||||
import org.apache.dubbo.rpc.AsyncRpcResult; | import org.apache.dubbo.rpc.AsyncRpcResult; | ||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; | import org.springframework.context.annotation.AnnotationConfigApplicationContext; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collections; | |||||
import java.util.List; | import java.util.List; | ||||
/** | /** | ||||
@@ -125,18 +122,18 @@ public class FooConsumerBootstrap { | |||||
} | } | ||||
public static void registryCustomFallback() { | public static void registryCustomFallback() { | ||||
DubboFallbackRegistry.setConsumerFallback( | |||||
DubboAdapterGlobalConfig.setConsumerFallback( | |||||
(invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult("fallback", invocation)); | (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult("fallback", invocation)); | ||||
} | } | ||||
public static void registryCustomFallbackForCustomException() { | public static void registryCustomFallbackForCustomException() { | ||||
DubboFallbackRegistry.setConsumerFallback( | |||||
DubboAdapterGlobalConfig.setConsumerFallback( | |||||
(invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(new RuntimeException("fallback"), invocation)); | (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult(new RuntimeException("fallback"), invocation)); | ||||
} | } | ||||
public static void registryCustomFallbackWhenFallbackError() { | public static void registryCustomFallbackWhenFallbackError() { | ||||
DubboFallbackRegistry.setConsumerFallback( | |||||
DubboAdapterGlobalConfig.setConsumerFallback( | |||||
(invoker, invocation, ex) -> { | (invoker, invocation, ex) -> { | ||||
throw new RuntimeException("fallback"); | throw new RuntimeException("fallback"); | ||||
}); | }); | ||||
@@ -15,7 +15,7 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.demo.apache.dubbo; | 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.ConsumerConfiguration; | ||||
import com.alibaba.csp.sentinel.demo.apache.dubbo.consumer.FooServiceConsumer; | 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.RuleConstant; | ||||
@@ -102,7 +102,7 @@ public class FooConsumerExceptionDegradeBootstrap { | |||||
} | } | ||||
public static void registryCustomFallback() { | public static void registryCustomFallback() { | ||||
DubboFallbackRegistry.setConsumerFallback( | |||||
DubboAdapterGlobalConfig.setConsumerFallback( | |||||
(invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult("fallback", invocation)); | (invoker, invocation, ex) -> AsyncRpcResult.newDefaultAsyncResult("fallback", invocation)); | ||||
} | } | ||||