Fix sentinel-apache-dubbo-adapter full GC bug (#1431)
This commit is contained in:
parent
bd29e046e1
commit
5d439adf60
|
|
@ -16,13 +16,9 @@
|
||||||
package com.alibaba.csp.sentinel.adapter.dubbo;
|
package com.alibaba.csp.sentinel.adapter.dubbo;
|
||||||
|
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.Entry;
|
import org.apache.dubbo.rpc.Filter;
|
||||||
import com.alibaba.csp.sentinel.Tracer;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import com.alibaba.csp.sentinel.context.ContextUtil;
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
|
||||||
import org.apache.dubbo.rpc.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}.
|
* Base Class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}.
|
||||||
|
|
@ -30,52 +26,25 @@ import org.apache.dubbo.rpc.*;
|
||||||
* @author Zechao Zheng
|
* @author Zechao Zheng
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class BaseSentinelDubboFilter extends ListenableFilter {
|
public abstract class BaseSentinelDubboFilter implements Filter {
|
||||||
public BaseSentinelDubboFilter() {
|
|
||||||
this.listener = new SentinelDubboListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SentinelDubboListener implements Listener {
|
|
||||||
|
|
||||||
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
/**
|
||||||
onSuccess(appResponse, invoker);
|
* Get method name of dubbo rpc
|
||||||
}
|
*
|
||||||
|
* @param invoker
|
||||||
|
* @param invocation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
abstract String getMethodName(Invoker invoker, Invocation invocation);
|
||||||
|
|
||||||
//for compatible dubbo 2.7.5 rename onResponse to onMessage
|
/**
|
||||||
public void onMessage(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
* Get interface name of dubbo rpc
|
||||||
onSuccess(appResponse, invoker);
|
*
|
||||||
}
|
* @param invoker
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
abstract String getInterfaceName(Invoker invoker);
|
||||||
|
|
||||||
private void onSuccess(Result appResponse, Invoker<?> invoker) {
|
|
||||||
if (DubboConfig.getDubboBizExceptionTraceEnabled()) {
|
|
||||||
traceAndExit(appResponse.getException(), invoker.getUrl());
|
|
||||||
} else {
|
|
||||||
traceAndExit(null, invoker.getUrl());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
traceAndExit(t, invoker.getUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void traceAndExit(Throwable throwable, URL url) {
|
|
||||||
Entry interfaceEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY);
|
|
||||||
Entry methodEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY);
|
|
||||||
if (methodEntry != null) {
|
|
||||||
Tracer.traceEntry(throwable, methodEntry);
|
|
||||||
methodEntry.exit();
|
|
||||||
RpcContext.getContext().remove(DubboUtils.DUBBO_METHOD_ENTRY_KEY);
|
|
||||||
}
|
|
||||||
if (interfaceEntry != null) {
|
|
||||||
Tracer.traceEntry(throwable, interfaceEntry);
|
|
||||||
interfaceEntry.exit();
|
|
||||||
RpcContext.getContext().remove(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY);
|
|
||||||
}
|
|
||||||
if (CommonConstants.PROVIDER_SIDE.equals(url.getParameter(CommonConstants.SIDE_KEY))) {
|
|
||||||
ContextUtil.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ import org.apache.dubbo.rpc.Invoker;
|
||||||
public final class DubboUtils {
|
public final class DubboUtils {
|
||||||
|
|
||||||
public static final String SENTINEL_DUBBO_APPLICATION_KEY = "dubboApplication";
|
public static final String SENTINEL_DUBBO_APPLICATION_KEY = "dubboApplication";
|
||||||
public static final String DUBBO_METHOD_ENTRY_KEY = "dubboMethodEntry";
|
|
||||||
public static final String DUBBO_INTERFACE_ENTRY_KEY = "dubboInterfaceEntry";
|
|
||||||
|
|
||||||
public static String getApplication(Invocation invocation, String defaultValue) {
|
public static String getApplication(Invocation invocation, String defaultValue) {
|
||||||
if (invocation == null || invocation.getAttachments() == null) {
|
if (invocation == null || invocation.getAttachments() == null) {
|
||||||
|
|
@ -69,6 +67,13 @@ public final class DubboUtils {
|
||||||
return getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled());
|
return getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getInterfaceName(Invoker invoker) {
|
||||||
|
return DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey()
|
||||||
|
: invoker.getInterface().getName();
|
||||||
|
}
|
||||||
|
|
||||||
private DubboUtils() {
|
private DubboUtils() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import com.alibaba.csp.sentinel.Entry;
|
||||||
import com.alibaba.csp.sentinel.EntryType;
|
import com.alibaba.csp.sentinel.EntryType;
|
||||||
import com.alibaba.csp.sentinel.ResourceTypeConstants;
|
import com.alibaba.csp.sentinel.ResourceTypeConstants;
|
||||||
import com.alibaba.csp.sentinel.SphU;
|
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.config.DubboConfig;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
|
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
|
||||||
import com.alibaba.csp.sentinel.log.RecordLog;
|
import com.alibaba.csp.sentinel.log.RecordLog;
|
||||||
|
|
@ -28,10 +29,12 @@ import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.InvokeMode;
|
import org.apache.dubbo.rpc.InvokeMode;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.Result;
|
import org.apache.dubbo.rpc.Result;
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
import org.apache.dubbo.rpc.support.RpcUtils;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -52,33 +55,85 @@ public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter {
|
||||||
RecordLog.info("Sentinel Apache Dubbo consumer filter initialized");
|
RecordLog.info("Sentinel Apache Dubbo consumer filter initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getMethodName(Invoker invoker, Invocation invocation) {
|
||||||
|
return DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getInterfaceName(Invoker invoker) {
|
||||||
|
return DubboUtils.getInterfaceName(invoker);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
||||||
|
InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation);
|
||||||
|
if (InvokeMode.SYNC == invokeMode) {
|
||||||
|
return syncInvoke(invoker, invocation);
|
||||||
|
} else {
|
||||||
|
return asyncInvoke(invoker, invocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result syncInvoke(Invoker<?> invoker, Invocation invocation) {
|
||||||
Entry interfaceEntry = null;
|
Entry interfaceEntry = null;
|
||||||
Entry methodEntry = null;
|
Entry methodEntry = null;
|
||||||
RpcContext rpcContext = RpcContext.getContext();
|
String methodResourceName = getMethodName(invoker, invocation);
|
||||||
|
String interfaceResourceName = getInterfaceName(invoker);
|
||||||
try {
|
try {
|
||||||
String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix());
|
|
||||||
String interfaceResourceName = DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey()
|
|
||||||
: invoker.getInterface().getName();
|
|
||||||
InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation);
|
|
||||||
|
|
||||||
if (InvokeMode.SYNC == invokeMode) {
|
|
||||||
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
|
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
|
||||||
rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry);
|
|
||||||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments());
|
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments());
|
||||||
} else {
|
Result result = invoker.invoke(invocation);
|
||||||
// should generate the AsyncEntry when the invoke model in future or async
|
if (result.hasException()) {
|
||||||
interfaceEntry = SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
|
Tracer.traceEntry(result.getException(), interfaceEntry);
|
||||||
rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry);
|
Tracer.traceEntry(result.getException(), methodEntry);
|
||||||
methodEntry = SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments());
|
|
||||||
}
|
}
|
||||||
rpcContext.set(DubboUtils.DUBBO_METHOD_ENTRY_KEY, methodEntry);
|
return result;
|
||||||
return invoker.invoke(invocation);
|
|
||||||
} catch (BlockException e) {
|
} catch (BlockException e) {
|
||||||
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e);
|
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e);
|
||||||
|
} catch (RpcException e) {
|
||||||
|
Tracer.traceEntry(e, interfaceEntry);
|
||||||
|
Tracer.traceEntry(e, methodEntry);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
if (methodEntry != null) {
|
||||||
|
methodEntry.exit();
|
||||||
|
}
|
||||||
|
if (interfaceEntry != null) {
|
||||||
|
interfaceEntry.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Result asyncInvoke(Invoker<?> invoker, Invocation invocation) {
|
||||||
|
LinkedList<Entry> queue = new LinkedList<>();
|
||||||
|
String methodResourceName = getMethodName(invoker, invocation);
|
||||||
|
String interfaceResourceName = getInterfaceName(invoker);
|
||||||
|
try {
|
||||||
|
queue.push(SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT));
|
||||||
|
queue.push(SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments()));
|
||||||
|
Result result = invoker.invoke(invocation);
|
||||||
|
result.whenCompleteWithContext(new BiConsumer<Result, Throwable>() {
|
||||||
|
@Override
|
||||||
|
public void accept(Result result, Throwable throwable) {
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
Entry entry = queue.pop();
|
||||||
|
Tracer.traceEntry(result.getException(), entry);
|
||||||
|
entry.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
} catch (BlockException e) {
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
queue.pop().exit();
|
||||||
|
}
|
||||||
|
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,17 @@ import com.alibaba.csp.sentinel.Entry;
|
||||||
import com.alibaba.csp.sentinel.EntryType;
|
import com.alibaba.csp.sentinel.EntryType;
|
||||||
import com.alibaba.csp.sentinel.ResourceTypeConstants;
|
import com.alibaba.csp.sentinel.ResourceTypeConstants;
|
||||||
import com.alibaba.csp.sentinel.SphU;
|
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.config.DubboConfig;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
|
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
|
||||||
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;
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
|
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
|
||||||
|
|
@ -52,27 +53,50 @@ public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter {
|
||||||
RecordLog.info("Sentinel Apache Dubbo provider filter initialized");
|
RecordLog.info("Sentinel Apache Dubbo provider filter initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getMethodName(Invoker invoker, Invocation invocation) {
|
||||||
|
return DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getInterfaceName(Invoker invoker) {
|
||||||
|
return DubboUtils.getInterfaceName(invoker);
|
||||||
|
}
|
||||||
|
|
||||||
@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 application = DubboUtils.getApplication(invocation, "");
|
||||||
RpcContext rpcContext = RpcContext.getContext();
|
|
||||||
Entry interfaceEntry = null;
|
Entry interfaceEntry = null;
|
||||||
Entry methodEntry = null;
|
Entry methodEntry = null;
|
||||||
|
String methodResourceName = getMethodName(invoker, invocation);
|
||||||
|
String interfaceResourceName = getInterfaceName(invoker);
|
||||||
try {
|
try {
|
||||||
String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix());
|
|
||||||
String interfaceResourceName = DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey()
|
|
||||||
: invoker.getInterface().getName();
|
|
||||||
// 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, application);
|
||||||
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN);
|
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN);
|
||||||
rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry);
|
|
||||||
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments());
|
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments());
|
||||||
rpcContext.set(DubboUtils.DUBBO_METHOD_ENTRY_KEY, methodEntry);
|
Result result = invoker.invoke(invocation);
|
||||||
return invoker.invoke(invocation);
|
if (result.hasException()) {
|
||||||
|
Tracer.traceEntry(result.getException(), interfaceEntry);
|
||||||
|
Tracer.traceEntry(result.getException(), methodEntry);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
} catch (BlockException e) {
|
} catch (BlockException e) {
|
||||||
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e);
|
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e);
|
||||||
|
} catch (RpcException e) {
|
||||||
|
Tracer.traceEntry(e, interfaceEntry);
|
||||||
|
Tracer.traceEntry(e, methodEntry);
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
if (methodEntry != null) {
|
||||||
|
methodEntry.exit(1, invocation.getArguments());
|
||||||
|
}
|
||||||
|
if (interfaceEntry != null) {
|
||||||
|
interfaceEntry.exit();
|
||||||
|
}
|
||||||
|
ContextUtil.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,25 +16,19 @@
|
||||||
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.DubboConfig;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService;
|
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;
|
||||||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
|
||||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base test class, provide common methods for subClass
|
* Base test class, provide common methods for subClass
|
||||||
* The package is same as CtSph, to call CtSph.resetChainMap() method for test
|
* The package is same as CtSph, to call CtSph.resetChainMap() method for test
|
||||||
|
|
@ -42,46 +36,41 @@ import static org.mockito.Mockito.when;
|
||||||
* Note: Only for test. DO NOT USE IN PRODUCTION!
|
* Note: Only for test. DO NOT USE IN PRODUCTION!
|
||||||
*
|
*
|
||||||
* @author cdfive
|
* @author cdfive
|
||||||
|
* @author lianglin
|
||||||
*/
|
*/
|
||||||
public class BaseTest {
|
public class BaseTest {
|
||||||
|
|
||||||
|
|
||||||
protected Invoker invoker;
|
|
||||||
protected Invocation invocation;
|
|
||||||
|
|
||||||
public void constructInvokerAndInvocation() {
|
|
||||||
invoker = mock(Invoker.class);
|
|
||||||
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());
|
|
||||||
when(invoker.getUrl()).thenReturn(url);
|
|
||||||
when(invoker.getInterface()).thenReturn(DemoService.class);
|
|
||||||
|
|
||||||
invocation = mock(Invocation.class);
|
|
||||||
Method method = DemoService.class.getMethods()[0];
|
|
||||||
when(invocation.getMethodName()).thenReturn(method.getName());
|
|
||||||
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up resources for context, clusterNodeMap, processorSlotChainMap
|
* Clean up resources for context, clusterNodeMap, processorSlotChainMap
|
||||||
*/
|
*/
|
||||||
protected static void cleanUpAll() {
|
public void cleanUpAll() {
|
||||||
try {
|
try {
|
||||||
RpcContext.removeContext();
|
clearDubboContext();
|
||||||
|
cleanUpCstContext();
|
||||||
|
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanUpCstContext() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
ClusterBuilderSlot.getClusterNodeMap().clear();
|
ClusterBuilderSlot.getClusterNodeMap().clear();
|
||||||
CtSph.resetChainMap();
|
CtSph.resetChainMap();
|
||||||
Method method = ContextUtil.class.getDeclaredMethod("resetContextMap");
|
Method method = ContextUtil.class.getDeclaredMethod("resetContextMap");
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
method.invoke(null, null);
|
method.invoke(null, null);
|
||||||
ContextUtil.exit();
|
ContextUtil.exit();
|
||||||
SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "true");
|
|
||||||
FlowRuleManager.loadRules(new ArrayList<>());
|
FlowRuleManager.loadRules(new ArrayList<>());
|
||||||
DegradeRuleManager.loadRules(new ArrayList<>());
|
DegradeRuleManager.loadRules(new ArrayList<>());
|
||||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
}
|
||||||
e.printStackTrace();
|
|
||||||
}
|
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());
|
||||||
|
RpcContext.removeContext();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.alibaba.csp.sentinel;
|
||||||
|
|
||||||
|
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService;
|
||||||
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.common.constants.CommonConstants;
|
||||||
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lianglin
|
||||||
|
*/
|
||||||
|
public class DubboTestUtil {
|
||||||
|
|
||||||
|
|
||||||
|
public static Class<?> DEFAULT_TEST_SERVICE = DemoService.class;
|
||||||
|
public static Method DEFAULT_TEST_METHOD_ONE = DEFAULT_TEST_SERVICE.getMethods()[0];
|
||||||
|
public static Method DEFAULT_TEST_METHOD_TWO = DEFAULT_TEST_SERVICE.getMethods()[1];
|
||||||
|
|
||||||
|
public static Invoker getMockInvoker(URL url, Class<?> cls) {
|
||||||
|
Invoker invoker = mock(Invoker.class);
|
||||||
|
when(invoker.getUrl()).thenReturn(url);
|
||||||
|
when(invoker.getInterface()).thenReturn(cls);
|
||||||
|
return invoker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Invoker getDefaultMockInvoker() {
|
||||||
|
return getMockInvoker(getDefaultTestURL(), DEFAULT_TEST_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Invocation getMockInvocation(Method method) {
|
||||||
|
Invocation invocation = mock(Invocation.class);
|
||||||
|
when(invocation.getMethodName()).thenReturn(method.getName());
|
||||||
|
when(invocation.getParameterTypes()).thenReturn(method.getParameterTypes());
|
||||||
|
return invocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Invocation getDefaultMockInvocationOne() {
|
||||||
|
Invocation invocation = mock(Invocation.class);
|
||||||
|
when(invocation.getMethodName()).thenReturn(DEFAULT_TEST_METHOD_ONE.getName());
|
||||||
|
when(invocation.getParameterTypes()).thenReturn(DEFAULT_TEST_METHOD_ONE.getParameterTypes());
|
||||||
|
return invocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Invocation getDefaultMockInvocationTwo() {
|
||||||
|
Invocation invocation = mock(Invocation.class);
|
||||||
|
when(invocation.getMethodName()).thenReturn(DEFAULT_TEST_METHOD_TWO.getName());
|
||||||
|
when(invocation.getParameterTypes()).thenReturn(DEFAULT_TEST_METHOD_TWO.getParameterTypes());
|
||||||
|
return invocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static URL getDefaultTestURL() {
|
||||||
|
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, DEFAULT_TEST_SERVICE.getName());
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,11 +29,10 @@ 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 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.mock;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author cdfive
|
* @author cdfive
|
||||||
|
|
@ -45,7 +44,7 @@ public class DubboUtilsTest {
|
||||||
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_PROVIDER_PREFIX, "");
|
||||||
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, "");
|
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, "");
|
||||||
SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false");
|
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -54,7 +53,7 @@ public class DubboUtilsTest {
|
||||||
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_PROVIDER_PREFIX, "");
|
||||||
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, "");
|
SentinelConfig.setConfig(DubboConfig.DUBBO_CONSUMER_PREFIX, "");
|
||||||
SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false");
|
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -146,4 +145,23 @@ public class DubboUtilsTest {
|
||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetInterfaceName() {
|
||||||
|
|
||||||
|
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, "false");
|
||||||
|
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService", DubboUtils.getInterfaceName(invoker));
|
||||||
|
|
||||||
|
SentinelConfig.setConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "true");
|
||||||
|
assertEquals("com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService:1.0.0:grp1", DubboUtils.getInterfaceName(invoker));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -16,13 +16,11 @@
|
||||||
package com.alibaba.csp.sentinel.adapter.dubbo;
|
package com.alibaba.csp.sentinel.adapter.dubbo;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.BaseTest;
|
import com.alibaba.csp.sentinel.BaseTest;
|
||||||
|
import com.alibaba.csp.sentinel.DubboTestUtil;
|
||||||
import com.alibaba.csp.sentinel.Entry;
|
import com.alibaba.csp.sentinel.Entry;
|
||||||
import com.alibaba.csp.sentinel.EntryType;
|
import com.alibaba.csp.sentinel.EntryType;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
|
|
||||||
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.fallback.DubboFallback;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
|
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService;
|
|
||||||
import com.alibaba.csp.sentinel.context.Context;
|
import com.alibaba.csp.sentinel.context.Context;
|
||||||
import com.alibaba.csp.sentinel.context.ContextUtil;
|
import com.alibaba.csp.sentinel.context.ContextUtil;
|
||||||
import com.alibaba.csp.sentinel.node.ClusterNode;
|
import com.alibaba.csp.sentinel.node.ClusterNode;
|
||||||
|
|
@ -36,8 +34,10 @@ 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.AsyncRpcResult;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
|
import org.apache.dubbo.rpc.InvokeMode;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.Result;
|
import org.apache.dubbo.rpc.Result;
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
|
|
@ -46,7 +46,6 @@ import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -56,105 +55,80 @@ import java.util.Set;
|
||||||
|
|
||||||
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;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.junit.Assert.assertNotSame;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author cdfive
|
* @author cdfive
|
||||||
|
* @author lianglin
|
||||||
*/
|
*/
|
||||||
public class SentinelDubboConsumerFilterTest extends BaseTest {
|
public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
|
|
||||||
private SentinelDubboConsumerFilter filter = new SentinelDubboConsumerFilter();
|
private SentinelDubboConsumerFilter consumerFilter = new SentinelDubboConsumerFilter();
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
cleanUpAll();
|
cleanUpAll();
|
||||||
initFallback();
|
initFallback();
|
||||||
constructInvokerAndInvocation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void cleanUp() {
|
public void destroy() {
|
||||||
cleanUpAll();
|
cleanUpAll();
|
||||||
DubboFallbackRegistry.setConsumerFallback(new DefaultDubboFallback());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initFlowRule(String resource) {
|
|
||||||
FlowRule flowRule = new FlowRule(resource);
|
|
||||||
flowRule.setCount(1);
|
|
||||||
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
|
||||||
List<FlowRule> flowRules = new ArrayList<>();
|
|
||||||
flowRules.add(flowRule);
|
|
||||||
FlowRuleManager.loadRules(flowRules);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initDegradeRule(String resource) {
|
|
||||||
DegradeRule degradeRule = new DegradeRule(resource)
|
|
||||||
.setCount(0.5)
|
|
||||||
.setGrade(DEGRADE_GRADE_EXCEPTION_RATIO);
|
|
||||||
List<DegradeRule> degradeRules = new ArrayList<>();
|
|
||||||
degradeRules.add(degradeRule);
|
|
||||||
degradeRule.setTimeWindow(1);
|
|
||||||
DegradeRuleManager.loadRules(degradeRules);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void initFallback() {
|
|
||||||
DubboFallbackRegistry.setConsumerFallback(new DubboFallback() {
|
|
||||||
@Override
|
|
||||||
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex) {
|
|
||||||
boolean async = RpcUtils.isAsync(invoker.getUrl(), invocation);
|
|
||||||
Result fallbackResult = null;
|
|
||||||
fallbackResult = AsyncRpcResult.newDefaultAsyncResult("fallback", invocation);
|
|
||||||
return fallbackResult;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInterfaceLevelFollowControlAsync() throws InterruptedException {
|
public void testInterfaceLevelFollowControlAsync() throws InterruptedException {
|
||||||
|
|
||||||
|
Invoker invoker = DubboTestUtil.getDefaultMockInvoker();
|
||||||
|
Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne();
|
||||||
|
|
||||||
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
||||||
initFlowRule(invoker.getUrl().getColonSeparatedKey());
|
initFlowRule(DubboUtils.getInterfaceName(invoker));
|
||||||
Result result1 = responseBack(requestGo(false, invocation));
|
|
||||||
|
Result result1 = invokeDubboRpc(false, invoker, invocation);
|
||||||
assertEquals("normal", result1.getValue());
|
assertEquals("normal", result1.getValue());
|
||||||
|
|
||||||
// should fallback because the qps > 1
|
// should fallback because the qps > 1
|
||||||
Result result2 = responseBack(requestGo(false, invocation));
|
Result result2 = invokeDubboRpc(false, invoker, invocation);
|
||||||
assertEquals("fallback", result2.getValue());
|
assertEquals("fallback", result2.getValue());
|
||||||
|
|
||||||
// sleeping 1000 ms to reset qps
|
// sleeping 1000 ms to reset qps
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
Result result3 = responseBack(requestGo(false, invocation));
|
Result result3 = invokeDubboRpc(false, invoker, invocation);
|
||||||
assertEquals("normal", result3.getValue());
|
assertEquals("normal", result3.getValue());
|
||||||
|
|
||||||
verifyInvocationStructureForCallFinish();
|
verifyInvocationStructureForCallFinish(invoker, invocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDegradeAsync() throws InterruptedException {
|
public void testDegradeAsync() throws InterruptedException {
|
||||||
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
|
||||||
|
|
||||||
initDegradeRule(invoker.getUrl().getColonSeparatedKey());
|
Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne();
|
||||||
Result result = requestGo(false, invocation);
|
Invoker invoker = DubboTestUtil.getDefaultMockInvoker();
|
||||||
verifyInvocationStructureForAsyncCall(invoker, invocation);
|
|
||||||
responseBack(result);
|
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
||||||
|
initDegradeRule(DubboUtils.getInterfaceName(invoker));
|
||||||
|
|
||||||
|
Result result = invokeDubboRpc(false, invoker, invocation);
|
||||||
|
verifyInvocationStructureForCallFinish(invoker, invocation);
|
||||||
assertEquals("normal", result.getValue());
|
assertEquals("normal", result.getValue());
|
||||||
|
|
||||||
|
|
||||||
// inc the clusterNode's exception to trigger the fallback
|
// inc the clusterNode's exception to trigger the fallback
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
responseBack(requestGo(true, invocation));
|
invokeDubboRpc(true, invoker, invocation);
|
||||||
verifyInvocationStructureForCallFinish();
|
verifyInvocationStructureForCallFinish(invoker, invocation);
|
||||||
}
|
}
|
||||||
Result result2 = responseBack(requestGo(false, invocation));
|
|
||||||
|
Result result2 = invokeDubboRpc(false, invoker, invocation);
|
||||||
assertEquals("fallback", result2.getValue());
|
assertEquals("fallback", result2.getValue());
|
||||||
|
|
||||||
// sleeping 1000 ms to reset exception
|
// sleeping 1000 ms to reset exception
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
Result result3 = invokeDubboRpc(false, invoker, invocation);
|
||||||
Result result3 = responseBack(requestGo(false, invocation));
|
|
||||||
assertEquals("normal", result3.getValue());
|
assertEquals("normal", result3.getValue());
|
||||||
|
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
|
|
@ -164,22 +138,26 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDegradeSync() throws InterruptedException {
|
public void testDegradeSync() throws InterruptedException {
|
||||||
|
|
||||||
initDegradeRule(invoker.getUrl().getColonSeparatedKey());
|
Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne();
|
||||||
Result result = requestGo(false, invocation);
|
Invoker invoker = DubboTestUtil.getDefaultMockInvoker();
|
||||||
verifyInvocationStructure(invoker, invocation);
|
initDegradeRule(DubboUtils.getInterfaceName(invoker));
|
||||||
responseBack(result);
|
|
||||||
|
Result result = invokeDubboRpc(false, invoker, invocation);
|
||||||
|
verifyInvocationStructureForCallFinish(invoker, invocation);
|
||||||
assertEquals("normal", result.getValue());
|
assertEquals("normal", result.getValue());
|
||||||
|
|
||||||
// inc the clusterNode's exception to trigger the fallback
|
// inc the clusterNode's exception to trigger the fallback
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
responseBack(requestGo(true, invocation));
|
invokeDubboRpc(true, invoker, invocation);
|
||||||
verifyInvocationStructureForCallFinish();
|
verifyInvocationStructureForCallFinish(invoker, invocation);
|
||||||
}
|
}
|
||||||
Result result2 = responseBack(requestGo(false, invocation));
|
|
||||||
|
Result result2 = invokeDubboRpc(false, invoker, invocation);
|
||||||
assertEquals("fallback", result2.getValue());
|
assertEquals("fallback", result2.getValue());
|
||||||
|
|
||||||
// sleeping 1000 ms to reset exception
|
// sleeping 1000 ms to reset exception
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
|
Result result3 = invokeDubboRpc(false, invoker, invocation);
|
||||||
Result result3 = responseBack(requestGo(false, invocation));
|
|
||||||
assertEquals("normal", result3.getValue());
|
assertEquals("normal", result3.getValue());
|
||||||
|
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
|
|
@ -189,62 +167,43 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMethodFlowControlAsync() {
|
public void testMethodFlowControlAsync() {
|
||||||
|
|
||||||
|
Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne();
|
||||||
|
Invoker invoker = DubboTestUtil.getDefaultMockInvoker();
|
||||||
|
|
||||||
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
||||||
initFlowRule(DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix()));
|
initFlowRule(consumerFilter.getMethodName(invoker, invocation));
|
||||||
responseBack(requestGo(false, invocation));
|
invokeDubboRpc(false, invoker, invocation);
|
||||||
|
invokeDubboRpc(false, invoker, invocation);
|
||||||
|
|
||||||
responseBack(requestGo(false, invocation));
|
Invocation invocation2 = DubboTestUtil.getDefaultMockInvocationTwo();
|
||||||
|
Result result2 = invokeDubboRpc(false, invoker, invocation2);
|
||||||
Invocation invocation2 = mock(Invocation.class);
|
verifyInvocationStructureForCallFinish(invoker, invocation2);
|
||||||
Method method = DemoService.class.getMethods()[1];
|
|
||||||
when(invocation2.getMethodName()).thenReturn(method.getName());
|
|
||||||
when(invocation2.getParameterTypes()).thenReturn(method.getParameterTypes());
|
|
||||||
Result result2 = responseBack(requestGo(false, invocation2));
|
|
||||||
verifyInvocationStructureForCallFinish();
|
|
||||||
assertEquals("normal", result2.getValue());
|
assertEquals("normal", result2.getValue());
|
||||||
|
|
||||||
// the method of invocation should be blocked
|
// the method of invocation should be blocked
|
||||||
Result fallback = requestGo(false, invocation);
|
Result fallback = invokeDubboRpc(false, invoker, invocation);
|
||||||
assertNotNull(RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY));
|
|
||||||
assertNull(RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY));
|
|
||||||
responseBack(fallback);
|
|
||||||
assertEquals("fallback", fallback.getValue());
|
assertEquals("fallback", fallback.getValue());
|
||||||
verifyInvocationStructureForCallFinish();
|
verifyInvocationStructureForCallFinish(invoker, invocation);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result requestGo(boolean exception, Invocation currentInvocation) {
|
|
||||||
AsyncRpcResult result = null;
|
|
||||||
|
|
||||||
if (exception) {
|
|
||||||
result = AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), currentInvocation);
|
|
||||||
} else {
|
|
||||||
result = AsyncRpcResult.newDefaultAsyncResult("normal", currentInvocation);
|
|
||||||
}
|
|
||||||
when(invoker.invoke(currentInvocation)).thenReturn(result);
|
|
||||||
return filter.invoke(invoker, currentInvocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result responseBack(Result result) {
|
|
||||||
filter.listener().onMessage(result, invoker, invocation);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvokeAsync() throws InterruptedException {
|
public void testInvokeAsync() {
|
||||||
|
|
||||||
|
Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne();
|
||||||
|
Invoker invoker = DubboTestUtil.getDefaultMockInvoker();
|
||||||
|
|
||||||
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
when(invocation.getAttachment(ASYNC_KEY)).thenReturn(Boolean.TRUE.toString());
|
||||||
|
|
||||||
final Result result = mock(Result.class);
|
final Result result = mock(Result.class);
|
||||||
when(result.hasException()).thenReturn(false);
|
when(result.hasException()).thenReturn(false);
|
||||||
when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> {
|
when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> {
|
||||||
verifyInvocationStructureForAsyncCall(invoker, invocation);
|
verifyInvocationStructureForAsyncCall(invoker, invocation);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
consumerFilter.invoke(invoker, invocation);
|
||||||
filter.invoke(invoker, invocation);
|
|
||||||
verify(invoker).invoke(invocation);
|
verify(invoker).invoke(invocation);
|
||||||
|
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
|
|
@ -254,6 +213,9 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
@Test
|
@Test
|
||||||
public void testInvokeSync() {
|
public void testInvokeSync() {
|
||||||
|
|
||||||
|
Invocation invocation = DubboTestUtil.getDefaultMockInvocationOne();
|
||||||
|
Invoker invoker = DubboTestUtil.getDefaultMockInvoker();
|
||||||
|
|
||||||
final Result result = mock(Result.class);
|
final Result result = mock(Result.class);
|
||||||
when(result.hasException()).thenReturn(false);
|
when(result.hasException()).thenReturn(false);
|
||||||
when(result.getException()).thenReturn(new Exception());
|
when(result.getException()).thenReturn(new Exception());
|
||||||
|
|
@ -262,14 +224,14 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
filter.invoke(invoker, invocation);
|
consumerFilter.invoke(invoker, invocation);
|
||||||
verify(invoker).invoke(invocation);
|
verify(invoker).invoke(invocation);
|
||||||
|
|
||||||
filter.listener().onMessage(result, invoker, invocation);
|
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
assertNull(context);
|
assertNull(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simply verify invocation structure in memory:
|
* Simply verify invocation structure in memory:
|
||||||
* EntranceNode(defaultContextName)
|
* EntranceNode(defaultContextName)
|
||||||
|
|
@ -282,7 +244,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 = DubboUtils.getResourceName(invoker, invocation, true);
|
String resourceName = consumerFilter.getMethodName(invoker, invocation);
|
||||||
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());
|
||||||
|
|
||||||
|
|
@ -295,10 +257,10 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
// As SphU.entry(interfaceName, EntryType.OUT);
|
// As SphU.entry(interfaceName, EntryType.OUT);
|
||||||
Set<Node> childList = entranceNode.getChildList();
|
Set<Node> childList = entranceNode.getChildList();
|
||||||
assertEquals(1, childList.size());
|
assertEquals(1, childList.size());
|
||||||
DefaultNode interfaceNode = getNode(invoker.getUrl().getColonSeparatedKey(), entranceNode);
|
DefaultNode interfaceNode = getNode(DubboUtils.getInterfaceName(invoker), entranceNode);
|
||||||
ResourceWrapper interfaceResource = interfaceNode.getId();
|
ResourceWrapper interfaceResource = interfaceNode.getId();
|
||||||
|
|
||||||
assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName());
|
assertEquals(DubboUtils.getInterfaceName(invoker), interfaceResource.getName());
|
||||||
assertSame(EntryType.OUT, interfaceResource.getEntryType());
|
assertSame(EntryType.OUT, interfaceResource.getEntryType());
|
||||||
|
|
||||||
// As SphU.entry(resourceName, EntryType.OUT);
|
// As SphU.entry(resourceName, EntryType.OUT);
|
||||||
|
|
@ -335,7 +297,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 = DubboUtils.getResourceName(invoker, invocation, true);
|
String resourceName = consumerFilter.getMethodName(invoker, invocation);
|
||||||
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());
|
||||||
|
|
||||||
|
|
@ -347,9 +309,9 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
// As SphU.entry(interfaceName, EntryType.OUT);
|
// As SphU.entry(interfaceName, EntryType.OUT);
|
||||||
Set<Node> childList = entranceNode.getChildList();
|
Set<Node> childList = entranceNode.getChildList();
|
||||||
assertEquals(2, childList.size());
|
assertEquals(2, childList.size());
|
||||||
DefaultNode interfaceNode = getNode(invoker.getUrl().getColonSeparatedKey(), entranceNode);
|
DefaultNode interfaceNode = getNode(DubboUtils.getInterfaceName(invoker), entranceNode);
|
||||||
ResourceWrapper interfaceResource = interfaceNode.getId();
|
ResourceWrapper interfaceResource = interfaceNode.getId();
|
||||||
assertEquals(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName());
|
assertEquals(DubboUtils.getInterfaceName(invoker), interfaceResource.getName());
|
||||||
assertSame(EntryType.OUT, interfaceResource.getEntryType());
|
assertSame(EntryType.OUT, interfaceResource.getEntryType());
|
||||||
|
|
||||||
// As SphU.entry(resourceName, EntryType.OUT);
|
// As SphU.entry(resourceName, EntryType.OUT);
|
||||||
|
|
@ -379,17 +341,16 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void verifyInvocationStructureForCallFinish() {
|
private void verifyInvocationStructureForCallFinish(Invoker invoker, Invocation invocation) {
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
assertNull(context);
|
assertNull(context);
|
||||||
Entry interfaceEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY);
|
String methodResourceName = consumerFilter.getMethodName(invoker, invocation);
|
||||||
Entry methodEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY);
|
Entry[] entries = (Entry[]) RpcContext.getContext().get(methodResourceName);
|
||||||
assertNull(interfaceEntry);
|
assertNull(entries);
|
||||||
assertNull(methodEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DefaultNode getNode(String resourceName, DefaultNode root) {
|
private DefaultNode getNode(String resourceName, DefaultNode root) {
|
||||||
|
|
||||||
Queue<DefaultNode> queue = new LinkedList<>();
|
Queue<DefaultNode> queue = new LinkedList<>();
|
||||||
queue.offer(root);
|
queue.offer(root);
|
||||||
|
|
@ -405,4 +366,52 @@ public class SentinelDubboConsumerFilterTest extends BaseTest {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initFlowRule(String resource) {
|
||||||
|
FlowRule flowRule = new FlowRule(resource);
|
||||||
|
flowRule.setCount(1);
|
||||||
|
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
|
||||||
|
List<FlowRule> flowRules = new ArrayList<>();
|
||||||
|
flowRules.add(flowRule);
|
||||||
|
FlowRuleManager.loadRules(flowRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDegradeRule(String resource) {
|
||||||
|
DegradeRule degradeRule = new DegradeRule(resource)
|
||||||
|
.setCount(0.5)
|
||||||
|
.setGrade(DEGRADE_GRADE_EXCEPTION_RATIO);
|
||||||
|
List<DegradeRule> degradeRules = new ArrayList<>();
|
||||||
|
degradeRules.add(degradeRule);
|
||||||
|
degradeRule.setTimeWindow(1);
|
||||||
|
DegradeRuleManager.loadRules(degradeRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initFallback() {
|
||||||
|
DubboFallbackRegistry.setConsumerFallback(new DubboFallback() {
|
||||||
|
@Override
|
||||||
|
public Result handle(Invoker<?> invoker, Invocation invocation, BlockException ex) {
|
||||||
|
boolean async = RpcUtils.isAsync(invoker.getUrl(), invocation);
|
||||||
|
Result fallbackResult = null;
|
||||||
|
fallbackResult = AsyncRpcResult.newDefaultAsyncResult("fallback", invocation);
|
||||||
|
return fallbackResult;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result invokeDubboRpc(boolean exception, Invoker invoker, Invocation invocation) {
|
||||||
|
Result result = null;
|
||||||
|
InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation);
|
||||||
|
if (InvokeMode.SYNC == invokeMode) {
|
||||||
|
result = exception ? new AppResponse(new Exception("error")) : new AppResponse("normal");
|
||||||
|
} else {
|
||||||
|
result = exception ? AsyncRpcResult.newDefaultAsyncResult(new Exception("error"), invocation) : AsyncRpcResult.newDefaultAsyncResult("normal", invocation);
|
||||||
|
}
|
||||||
|
when(invoker.invoke(invocation)).thenReturn(result);
|
||||||
|
return consumerFilter.invoke(invoker, invocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
package com.alibaba.csp.sentinel.adapter.dubbo;
|
package com.alibaba.csp.sentinel.adapter.dubbo;
|
||||||
|
|
||||||
import com.alibaba.csp.sentinel.BaseTest;
|
import com.alibaba.csp.sentinel.BaseTest;
|
||||||
|
import com.alibaba.csp.sentinel.DubboTestUtil;
|
||||||
import com.alibaba.csp.sentinel.Entry;
|
import com.alibaba.csp.sentinel.Entry;
|
||||||
import com.alibaba.csp.sentinel.EntryType;
|
import com.alibaba.csp.sentinel.EntryType;
|
||||||
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService;
|
import com.alibaba.csp.sentinel.adapter.dubbo.provider.DemoService;
|
||||||
|
|
@ -35,52 +36,49 @@ import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.junit.Assert.assertNotSame;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author cdfive
|
* @author cdfive
|
||||||
|
* @author lianglin
|
||||||
*/
|
*/
|
||||||
public class SentinelDubboProviderFilterTest extends BaseTest {
|
public class SentinelDubboProviderFilterTest extends BaseTest {
|
||||||
|
|
||||||
|
|
||||||
private SentinelDubboProviderFilter filter = new SentinelDubboProviderFilter();
|
private SentinelDubboProviderFilter filter = new SentinelDubboProviderFilter();
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
constructInvokerAndInvocation();
|
|
||||||
cleanUpAll();
|
cleanUpAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void cleanUp() {
|
public void destroy() {
|
||||||
cleanUpAll();
|
cleanUpAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvoke() {
|
public void testInvoke() {
|
||||||
|
|
||||||
final String originApplication = "consumerA";
|
final String originApplication = "consumerA";
|
||||||
|
|
||||||
URL url = invoker.getUrl()
|
URL url = DubboTestUtil.getDefaultTestURL();
|
||||||
.addParameter(CommonConstants.SIDE_KEY, CommonConstants.PROVIDER_SIDE);
|
url = url.addParameter(CommonConstants.SIDE_KEY, CommonConstants.PROVIDER_SIDE);
|
||||||
when(invoker.getUrl()).thenReturn(url);
|
Invoker invoker = DubboTestUtil.getMockInvoker(url, DemoService.class);
|
||||||
|
|
||||||
|
Invocation invocation = DubboTestUtil.getMockInvocation(DemoService.class.getMethods()[0]);
|
||||||
when(invocation.getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, ""))
|
when(invocation.getAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, ""))
|
||||||
.thenReturn(originApplication);
|
.thenReturn(originApplication);
|
||||||
|
|
||||||
final Result result = mock(Result.class);
|
final Result result = mock(Result.class);
|
||||||
when(result.hasException()).thenReturn(false);
|
when(result.hasException()).thenReturn(false);
|
||||||
when(result.getException()).thenReturn(new Exception());
|
when(result.getException()).thenReturn(new Exception());
|
||||||
|
|
||||||
when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> {
|
when(invoker.invoke(invocation)).thenAnswer(invocationOnMock -> {
|
||||||
verifyInvocationStructure(originApplication, invoker, invocation);
|
verifyInvocationStructure(originApplication, invoker, invocation);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -89,29 +87,28 @@ public class SentinelDubboProviderFilterTest extends BaseTest {
|
||||||
filter.invoke(invoker, invocation);
|
filter.invoke(invoker, invocation);
|
||||||
verify(invoker).invoke(invocation);
|
verify(invoker).invoke(invocation);
|
||||||
|
|
||||||
filter.listener().onMessage(result, invoker, invocation);
|
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
assertNull(context);
|
assertNull(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simply verify invocation structure in memory:
|
* Simply verify invocation structure in memory:
|
||||||
* EntranceNode(resourceName)
|
* EntranceNode(methodResourceName)
|
||||||
* --InterfaceNode(interfaceName)
|
* --InterfaceNode(interfaceName)
|
||||||
* ----MethodNode(resourceName)
|
* ----MethodNode(methodResourceName)
|
||||||
*/
|
*/
|
||||||
private void verifyInvocationStructure(String originApplication, Invoker invoker, Invocation invocation) {
|
private void verifyInvocationStructure(String originApplication, Invoker invoker, Invocation invocation) {
|
||||||
Context context = ContextUtil.getContext();
|
Context context = ContextUtil.getContext();
|
||||||
assertNotNull(context);
|
assertNotNull(context);
|
||||||
|
|
||||||
// As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter
|
// As ContextUtil.enter(resourceName, application) in SentinelDubboProviderFilter
|
||||||
String resourceName = DubboUtils.getResourceName(invoker, invocation, true);
|
String methodResourceName = filter.getMethodName(invoker, invocation);
|
||||||
assertEquals(resourceName, context.getName());
|
assertEquals(methodResourceName, context.getName());
|
||||||
assertEquals(originApplication, context.getOrigin());
|
assertEquals(originApplication, context.getOrigin());
|
||||||
|
|
||||||
DefaultNode entranceNode = context.getEntranceNode();
|
DefaultNode entranceNode = context.getEntranceNode();
|
||||||
ResourceWrapper entranceResource = entranceNode.getId();
|
ResourceWrapper entranceResource = entranceNode.getId();
|
||||||
assertEquals(resourceName, entranceResource.getName());
|
assertEquals(methodResourceName, entranceResource.getName());
|
||||||
assertSame(EntryType.IN, entranceResource.getEntryType());
|
assertSame(EntryType.IN, entranceResource.getEntryType());
|
||||||
|
|
||||||
// As SphU.entry(interfaceName, EntryType.IN);
|
// As SphU.entry(interfaceName, EntryType.IN);
|
||||||
|
|
@ -120,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(invoker.getUrl().getColonSeparatedKey(), interfaceResource.getName());
|
assertEquals(filter.getInterfaceName(invoker), 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());
|
||||||
|
|
@ -128,7 +125,7 @@ public class SentinelDubboProviderFilterTest extends BaseTest {
|
||||||
assertEquals(1, childList.size());
|
assertEquals(1, childList.size());
|
||||||
DefaultNode methodNode = (DefaultNode) childList.iterator().next();
|
DefaultNode methodNode = (DefaultNode) childList.iterator().next();
|
||||||
ResourceWrapper methodResource = methodNode.getId();
|
ResourceWrapper methodResource = methodNode.getId();
|
||||||
assertEquals(resourceName, methodResource.getName());
|
assertEquals(methodResourceName, methodResource.getName());
|
||||||
assertSame(EntryType.IN, methodResource.getEntryType());
|
assertSame(EntryType.IN, methodResource.getEntryType());
|
||||||
|
|
||||||
// Verify curEntry
|
// Verify curEntry
|
||||||
|
|
@ -151,4 +148,6 @@ public class SentinelDubboProviderFilterTest extends BaseTest {
|
||||||
assertEquals(1, interfaceOriginCountMap.size());
|
assertEquals(1, interfaceOriginCountMap.size());
|
||||||
assertTrue(interfaceOriginCountMap.containsKey(originApplication));
|
assertTrue(interfaceOriginCountMap.containsKey(originApplication));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue