Skip to content

Commit 9d311f2

Browse files
committed
support apache dubbo asynchronous call #1114
1 parent c705651 commit 9d311f2

File tree

13 files changed

+407
-96
lines changed

13 files changed

+407
-96
lines changed

sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<properties>
1616
<java.source.version>1.8</java.source.version>
1717
<java.target.version>1.8</java.target.version>
18-
<apache.dubbo.version>2.7.1</apache.dubbo.version>
18+
<apache.dubbo.version>2.7.3</apache.dubbo.version>
1919
</properties>
2020

2121
<dependencies>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 1999-2018 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.dubbo;
17+
18+
19+
import com.alibaba.csp.sentinel.Entry;
20+
import com.alibaba.csp.sentinel.Tracer;
21+
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
22+
import com.alibaba.csp.sentinel.context.ContextUtil;
23+
import org.apache.dubbo.common.URL;
24+
import org.apache.dubbo.common.constants.CommonConstants;
25+
import org.apache.dubbo.rpc.Invocation;
26+
import org.apache.dubbo.rpc.Invoker;
27+
import org.apache.dubbo.rpc.ListenableFilter;
28+
import org.apache.dubbo.rpc.Result;
29+
import org.apache.dubbo.rpc.RpcContext;
30+
31+
/**
32+
* Base Class of the {@link SentinelDubboProviderFilter} and {@link SentinelDubboConsumerFilter}.
33+
*
34+
* @author Zechao Zheng
35+
*/
36+
37+
public abstract class BaseSentinelDubboFilter extends ListenableFilter {
38+
public BaseSentinelDubboFilter() {
39+
this.listener = new SentinelDubboListener();
40+
}
41+
42+
static class SentinelDubboListener implements Listener {
43+
44+
@Override
45+
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
46+
if (DubboConfig.getDubboBizExceptionTraceEnabled()) {
47+
traceAndExit(appResponse.getException(), invoker.getUrl());
48+
} else {
49+
traceAndExit(null, invoker.getUrl());
50+
}
51+
}
52+
53+
@Override
54+
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
55+
traceAndExit(t, invoker.getUrl());
56+
}
57+
58+
}
59+
60+
static void traceAndExit(Throwable throwable, URL url) {
61+
Entry interfaceEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY);
62+
Entry methodEntry = (Entry) RpcContext.getContext().get(DubboUtils.DUBBO_METHOD_ENTRY_KEY);
63+
if (methodEntry != null) {
64+
Tracer.traceEntry(throwable, methodEntry);
65+
methodEntry.exit();
66+
RpcContext.getContext().remove(DubboUtils.DUBBO_METHOD_ENTRY_KEY);
67+
}
68+
if (interfaceEntry != null) {
69+
Tracer.traceEntry(throwable, interfaceEntry);
70+
interfaceEntry.exit();
71+
RpcContext.getContext().remove(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY);
72+
}
73+
if (CommonConstants.PROVIDER_SIDE.equals(url.getParameter(CommonConstants.SIDE_KEY))) {
74+
ContextUtil.exit();
75+
}
76+
}
77+
}

sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboAppContextFilter.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.alibaba.csp.sentinel.adapter.dubbo;
1717

18-
import org.apache.dubbo.common.Constants;
18+
import org.apache.dubbo.common.constants.CommonConstants;
1919
import org.apache.dubbo.common.extension.Activate;
2020
import org.apache.dubbo.rpc.Filter;
2121
import org.apache.dubbo.rpc.Invocation;
@@ -34,7 +34,7 @@ public class DubboAppContextFilter implements Filter {
3434

3535
@Override
3636
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
37-
String application = invoker.getUrl().getParameter(Constants.APPLICATION_KEY);
37+
String application = invoker.getUrl().getParameter(CommonConstants.APPLICATION_KEY);
3838
if (application != null) {
3939
RpcContext.getContext().setAttachment(DubboUtils.SENTINEL_DUBBO_APPLICATION_KEY, application);
4040
}

sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/DubboUtils.java

+15-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.alibaba.csp.sentinel.adapter.dubbo;
1717

18+
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
1819
import com.alibaba.csp.sentinel.util.StringUtil;
1920
import org.apache.dubbo.rpc.Invocation;
2021
import org.apache.dubbo.rpc.Invoker;
@@ -25,6 +26,8 @@
2526
public final class DubboUtils {
2627

2728
public static final String SENTINEL_DUBBO_APPLICATION_KEY = "dubboApplication";
29+
public static final String DUBBO_METHOD_ENTRY_KEY = "dubboMethodEntry";
30+
public static final String DUBBO_INTERFACE_ENTRY_KEY = "dubboInterfaceEntry";
2831

2932
public static String getApplication(Invocation invocation, String defaultValue) {
3033
if (invocation == null || invocation.getAttachments() == null) {
@@ -33,12 +36,17 @@ public static String getApplication(Invocation invocation, String defaultValue)
3336
return invocation.getAttachment(SENTINEL_DUBBO_APPLICATION_KEY, defaultValue);
3437
}
3538

36-
public static String getResourceName(Invoker<?> invoker, Invocation invocation) {
39+
public static String getResourceName(Invoker<?> invoker, Invocation invocation){
40+
return getResourceName(invoker, invocation, false);
41+
}
42+
43+
public static String getResourceName(Invoker<?> invoker, Invocation invocation, Boolean useGroupAndVersion) {
3744
StringBuilder buf = new StringBuilder(64);
38-
buf.append(invoker.getInterface().getName())
39-
.append(":")
40-
.append(invocation.getMethodName())
41-
.append("(");
45+
String interfaceResource = useGroupAndVersion ? invoker.getUrl().getColonSeparatedKey() : invoker.getInterface().getName();
46+
buf.append(interfaceResource)
47+
.append(":")
48+
.append(invocation.getMethodName())
49+
.append("(");
4250
boolean isFirst = true;
4351
for (Class<?> clazz : invocation.getParameterTypes()) {
4452
if (!isFirst) {
@@ -55,13 +63,12 @@ public static String getResourceName(Invoker<?> invoker, Invocation invocation,
5563
if (StringUtil.isNotBlank(prefix)) {
5664
return new StringBuilder(64)
5765
.append(prefix)
58-
.append(getResourceName(invoker, invocation))
66+
.append(getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled()))
5967
.toString();
6068
} else {
61-
return getResourceName(invoker, invocation);
69+
return getResourceName(invoker, invocation, DubboConfig.getDubboInterfaceGroupAndVersionEnabled());
6270
}
6371
}
64-
6572
private DubboUtils() {
6673
}
6774
}

sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboConsumerFilter.java

100755100644
+21-25
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,18 @@
1919
import com.alibaba.csp.sentinel.EntryType;
2020
import com.alibaba.csp.sentinel.ResourceTypeConstants;
2121
import com.alibaba.csp.sentinel.SphU;
22-
import com.alibaba.csp.sentinel.Tracer;
2322
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
2423
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
2524
import com.alibaba.csp.sentinel.log.RecordLog;
2625
import com.alibaba.csp.sentinel.slots.block.BlockException;
2726
import org.apache.dubbo.common.extension.Activate;
28-
import org.apache.dubbo.rpc.Filter;
2927
import org.apache.dubbo.rpc.Invocation;
28+
import org.apache.dubbo.rpc.InvokeMode;
3029
import org.apache.dubbo.rpc.Invoker;
3130
import org.apache.dubbo.rpc.Result;
31+
import org.apache.dubbo.rpc.RpcContext;
3232
import org.apache.dubbo.rpc.RpcException;
33+
import org.apache.dubbo.rpc.support.RpcUtils;
3334

3435
/**
3536
* <p>Dubbo service consumer filter for Sentinel. Auto activated by default.</p>
@@ -43,7 +44,7 @@
4344
* @author Eric Zhao
4445
*/
4546
@Activate(group = "consumer")
46-
public class SentinelDubboConsumerFilter implements Filter {
47+
public class SentinelDubboConsumerFilter extends BaseSentinelDubboFilter {
4748

4849
public SentinelDubboConsumerFilter() {
4950
RecordLog.info("Sentinel Apache Dubbo consumer filter initialized");
@@ -53,33 +54,28 @@ public SentinelDubboConsumerFilter() {
5354
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
5455
Entry interfaceEntry = null;
5556
Entry methodEntry = null;
57+
RpcContext rpcContext = RpcContext.getContext();
5658
try {
57-
String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix());
58-
interfaceEntry = SphU.entry(invoker.getInterface().getName(),
59-
ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
60-
methodEntry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
59+
String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboConsumerPrefix());
60+
String interfaceResourceName = DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey()
61+
: invoker.getInterface().getName();
62+
InvokeMode invokeMode = RpcUtils.getInvokeMode(invoker.getUrl(), invocation);
6163

62-
Result result = invoker.invoke(invocation);
63-
if (result.hasException()) {
64-
Throwable e = result.getException();
65-
// Record common exception.
66-
Tracer.traceEntry(e, interfaceEntry);
67-
Tracer.traceEntry(e, methodEntry);
64+
if (InvokeMode.SYNC == invokeMode) {
65+
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
66+
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, invocation.getArguments());
67+
} else {
68+
// should generate the AsyncEntry when the invoke model in future or async
69+
interfaceEntry = SphU.asyncEntry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT);
70+
methodEntry = SphU.asyncEntry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.OUT, 1, invocation.getArguments());
6871
}
69-
return result;
72+
rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry);
73+
rpcContext.set(DubboUtils.DUBBO_METHOD_ENTRY_KEY, methodEntry);
74+
return invoker.invoke(invocation);
7075
} catch (BlockException e) {
7176
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e);
72-
} catch (RpcException e) {
73-
Tracer.traceEntry(e, interfaceEntry);
74-
Tracer.traceEntry(e, methodEntry);
75-
throw e;
76-
} finally {
77-
if (methodEntry != null) {
78-
methodEntry.exit();
79-
}
80-
if (interfaceEntry != null) {
81-
interfaceEntry.exit();
82-
}
8377
}
8478
}
8579
}
80+
81+

sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/SentinelDubboProviderFilter.java

100755100644
+15-31
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,16 @@
1919
import com.alibaba.csp.sentinel.EntryType;
2020
import com.alibaba.csp.sentinel.ResourceTypeConstants;
2121
import com.alibaba.csp.sentinel.SphU;
22-
import com.alibaba.csp.sentinel.Tracer;
2322
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
2423
import com.alibaba.csp.sentinel.adapter.dubbo.fallback.DubboFallbackRegistry;
2524
import com.alibaba.csp.sentinel.context.ContextUtil;
2625
import com.alibaba.csp.sentinel.log.RecordLog;
2726
import com.alibaba.csp.sentinel.slots.block.BlockException;
2827
import org.apache.dubbo.common.extension.Activate;
29-
import org.apache.dubbo.rpc.Filter;
3028
import org.apache.dubbo.rpc.Invocation;
3129
import org.apache.dubbo.rpc.Invoker;
3230
import org.apache.dubbo.rpc.Result;
31+
import org.apache.dubbo.rpc.RpcContext;
3332
import org.apache.dubbo.rpc.RpcException;
3433

3534
/**
@@ -45,7 +44,7 @@
4544
* @author Eric Zhao
4645
*/
4746
@Activate(group = "provider")
48-
public class SentinelDubboProviderFilter implements Filter {
47+
public class SentinelDubboProviderFilter extends BaseSentinelDubboFilter {
4948

5049
public SentinelDubboProviderFilter() {
5150
RecordLog.info("Sentinel Apache Dubbo provider filter initialized");
@@ -55,41 +54,26 @@ public SentinelDubboProviderFilter() {
5554
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
5655
// Get origin caller.
5756
String application = DubboUtils.getApplication(invocation, "");
58-
57+
RpcContext rpcContext = RpcContext.getContext();
5958
Entry interfaceEntry = null;
6059
Entry methodEntry = null;
6160
try {
62-
String resourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix());
63-
String interfaceName = invoker.getInterface().getName();
61+
String methodResourceName = DubboUtils.getResourceName(invoker, invocation, DubboConfig.getDubboProviderPrefix());
62+
String interfaceResourceName = DubboConfig.getDubboInterfaceGroupAndVersionEnabled() ? invoker.getUrl().getColonSeparatedKey()
63+
: invoker.getInterface().getName();
6464
// Only need to create entrance context at provider side, as context will take effect
6565
// at entrance of invocation chain only (for inbound traffic).
66-
ContextUtil.enter(resourceName, application);
67-
interfaceEntry = SphU.entry(interfaceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN);
68-
methodEntry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_RPC,
69-
EntryType.IN, invocation.getArguments());
70-
71-
Result result = invoker.invoke(invocation);
72-
if (result.hasException()) {
73-
Throwable e = result.getException();
74-
// Record common exception.
75-
Tracer.traceEntry(e, interfaceEntry);
76-
Tracer.traceEntry(e, methodEntry);
77-
}
78-
return result;
66+
ContextUtil.enter(methodResourceName, application);
67+
interfaceEntry = SphU.entry(interfaceResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN);
68+
methodEntry = SphU.entry(methodResourceName, ResourceTypeConstants.COMMON_RPC, EntryType.IN, invocation.getArguments());
69+
rpcContext.set(DubboUtils.DUBBO_INTERFACE_ENTRY_KEY, interfaceEntry);
70+
rpcContext.set(DubboUtils.DUBBO_METHOD_ENTRY_KEY, methodEntry);
71+
return invoker.invoke(invocation);
7972
} catch (BlockException e) {
8073
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e);
81-
} catch (RpcException e) {
82-
Tracer.traceEntry(e, interfaceEntry);
83-
Tracer.traceEntry(e, methodEntry);
84-
throw e;
85-
} finally {
86-
if (methodEntry != null) {
87-
methodEntry.exit(1, invocation.getArguments());
88-
}
89-
if (interfaceEntry != null) {
90-
interfaceEntry.exit();
91-
}
92-
ContextUtil.exit();
9374
}
9475
}
76+
77+
9578
}
79+

sentinel-adapter/sentinel-apache-dubbo-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/dubbo/config/DubboConfig.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ public final class DubboConfig {
3737
private static final String DEFAULT_DUBBO_PROVIDER_PREFIX = "dubbo:provider:";
3838
private static final String DEFAULT_DUBBO_CONSUMER_PREFIX = "dubbo:consumer:";
3939

40+
public static final String DUBBO_INTERFACE_GROUP_VERSION_ENABLED = "csp.sentinel.dubbo.interface.group.version.enabled";
4041

41-
public static boolean isUsePrefix(){
42+
public static final String TRACE_BIZ_EXCEPTION_ENABLED = "csp.sentinel.dubbo.trace.biz.exception.enabled";
43+
44+
45+
public static boolean isUsePrefix() {
4246
return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_USE_PREFIX));
4347
}
4448

@@ -58,5 +62,16 @@ public static String getDubboConsumerPrefix() {
5862
return null;
5963
}
6064

65+
public static Boolean getDubboInterfaceGroupAndVersionEnabled() {
66+
return TRUE_STR.equalsIgnoreCase(SentinelConfig.getConfig(DUBBO_INTERFACE_GROUP_VERSION_ENABLED));
67+
}
68+
69+
public static Boolean getDubboBizExceptionTraceEnabled() {
70+
String traceBizExceptionEnabled = SentinelConfig.getConfig(TRACE_BIZ_EXCEPTION_ENABLED);
71+
if (StringUtil.isNotBlank(traceBizExceptionEnabled)) {
72+
return TRUE_STR.equalsIgnoreCase(traceBizExceptionEnabled);
73+
}
74+
return true;
75+
}
6176

6277
}

sentinel-adapter/sentinel-apache-dubbo-adapter/src/test/java/com/alibaba/csp/sentinel/BaseTest.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515
*/
1616
package com.alibaba.csp.sentinel;
1717

18+
import com.alibaba.csp.sentinel.adapter.dubbo.config.DubboConfig;
19+
import com.alibaba.csp.sentinel.config.SentinelConfig;
20+
import com.alibaba.csp.sentinel.context.ContextUtil;
1821
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
1922

2023
import org.apache.dubbo.rpc.RpcContext;
2124

25+
import java.lang.reflect.InvocationTargetException;
26+
import java.lang.reflect.Method;
27+
2228
/**
2329
* Base test class, provide common methods for subClass
2430
* The package is same as CtSph, to call CtSph.resetChainMap() method for test
@@ -33,8 +39,17 @@ public class BaseTest {
3339
* Clean up resources for context, clusterNodeMap, processorSlotChainMap
3440
*/
3541
protected static void cleanUpAll() {
36-
RpcContext.removeContext();
37-
ClusterBuilderSlot.getClusterNodeMap().clear();
38-
CtSph.resetChainMap();
42+
try {
43+
RpcContext.removeContext();
44+
ClusterBuilderSlot.getClusterNodeMap().clear();
45+
CtSph.resetChainMap();
46+
Method method = ContextUtil.class.getDeclaredMethod("resetContextMap");
47+
method.setAccessible(true);
48+
method.invoke(null, null);
49+
ContextUtil.exit();
50+
SentinelConfig.setConfig(DubboConfig.DUBBO_INTERFACE_GROUP_VERSION_ENABLED, "true");
51+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
52+
e.printStackTrace();
53+
}
3954
}
4055
}

0 commit comments

Comments
 (0)