From 5da840dcdc011cbd6caece8bae312230409f8d8a Mon Sep 17 00:00:00 2001 From: "ken.lj" Date: Tue, 12 May 2020 01:29:09 +0800 Subject: [PATCH] Fix timeout 6008 (#6136) --- .../common/constants/CommonConstants.java | 4 +++ .../dubbo/rpc/filter/ContextFilter.java | 12 ++++--- .../apache/dubbo/rpc/support/RpcUtils.java | 3 +- .../protocol/dubbo/ChannelWrappedInvoker.java | 3 +- .../rpc/protocol/dubbo/DubboInvoker.java | 33 +++++++++++-------- .../rpc/protocol/thrift/ThriftInvoker.java | 2 +- 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index 27c5744cc5..cac52fe739 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -110,6 +110,10 @@ public interface CommonConstants { int DEFAULT_TIMEOUT = 1000; + // used by invocation attachments to transfer timeout from Consumer to Provider. + // works as a replacement of TIMEOUT_KEY on wire, which seems to be totally useless in previous releases). + String TIMEOUT_ATTACHENT_KEY = "_TO"; + String TIME_COUNTDOWN_KEY = "timeout-countdown"; String ENABLE_TIMEOUT_COUNTDOWN_KEY = "enable-timeout-countdown"; diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java index 0274474490..81ad8df2da 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java @@ -40,6 +40,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER; import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHENT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; @@ -70,6 +71,7 @@ public class ContextFilter implements Filter, Filter.Listener { UNLOADING_KEYS.add(DUBBO_VERSION_KEY); UNLOADING_KEYS.add(TOKEN_KEY); UNLOADING_KEYS.add(TIMEOUT_KEY); + UNLOADING_KEYS.add(TIMEOUT_ATTACHENT_KEY); // Remove async property to avoid being passed to the following invoke chain. UNLOADING_KEYS.add(ASYNC_KEY); @@ -103,6 +105,11 @@ public class ContextFilter implements Filter, Filter.Listener { context.setRemoteApplicationName((String) context.getAttachment(REMOTE_APPLICATION_KEY)); } + long timeout = RpcUtils.getTimeout(invocation, -1); + if (timeout != -1) { + context.set(TIME_COUNTDOWN_KEY, TimeoutCountDown.newCountDown(timeout, TimeUnit.MILLISECONDS)); + } + // merged from dubbox // we may already added some attachments into RpcContext before this filter (e.g. in rest protocol) if (attachments != null) { @@ -117,11 +124,6 @@ public class ContextFilter implements Filter, Filter.Listener { ((RpcInvocation) invocation).setInvoker(invoker); } - long timeout = RpcUtils.getTimeout(invocation, -1); - if (timeout != -1) { - context.set(TIME_COUNTDOWN_KEY, TimeoutCountDown.newCountDown(timeout, TimeUnit.MILLISECONDS)); - } - try { context.clearAfterEachInvoke(false); return invoker.invoke(invocation); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java index 9df1eea9d0..18f9f68552 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/RpcUtils.java @@ -34,6 +34,7 @@ import java.util.concurrent.atomic.AtomicLong; import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE; import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHENT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; import static org.apache.dubbo.rpc.Constants.$ECHO; import static org.apache.dubbo.rpc.Constants.ASYNC_KEY; @@ -216,7 +217,7 @@ public class RpcUtils { public static long getTimeout(Invocation invocation, long defaultTimeout) { long timeout = defaultTimeout; - Object genericTimeout = invocation.getObjectAttachment(TIMEOUT_KEY); + Object genericTimeout = invocation.getObjectAttachment(TIMEOUT_ATTACHENT_KEY); if (genericTimeout != null) { timeout = convertToNumber(genericTimeout, defaultTimeout); } diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java index 7f2a6cada0..cf8b569f2d 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/ChannelWrappedInvoker.java @@ -38,7 +38,6 @@ import java.util.concurrent.CompletableFuture; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; import static org.apache.dubbo.remoting.Constants.SENT_KEY; import static org.apache.dubbo.rpc.Constants.TOKEN_KEY; import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY; @@ -54,7 +53,7 @@ class ChannelWrappedInvoker extends AbstractInvoker { private final ExchangeClient currentClient; ChannelWrappedInvoker(Class serviceType, Channel channel, URL url, String serviceKey) { - super(serviceType, url, new String[]{GROUP_KEY, TOKEN_KEY, TIMEOUT_KEY}); + super(serviceType, url, new String[]{GROUP_KEY, TOKEN_KEY}); this.channel = channel; this.serviceKey = serviceKey; this.currentClient = new HeaderExchangeClient(new ChannelWrapper(this.channel), false); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java index 5ef50aad03..d88ae542e1 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java @@ -47,7 +47,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_TIMEOUT_C import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHENT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; import static org.apache.dubbo.rpc.Constants.TOKEN_KEY; @@ -72,7 +72,7 @@ public class DubboInvoker extends AbstractInvoker { } public DubboInvoker(Class serviceType, URL url, ExchangeClient[] clients, Set> invokers) { - super(serviceType, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY, TIMEOUT_KEY}); + super(serviceType, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY}); this.clients = clients; // get version. this.version = url.getParameter(VERSION_KEY, "0.0.0"); @@ -94,18 +94,7 @@ public class DubboInvoker extends AbstractInvoker { } try { boolean isOneway = RpcUtils.isOneway(getUrl(), invocation); - Object countdown = RpcContext.getContext().get(TIME_COUNTDOWN_KEY); - int timeout = DEFAULT_TIMEOUT; - if (countdown == null) { - timeout = (int) RpcUtils.getTimeout(getUrl(), methodName, RpcContext.getContext(), DEFAULT_TIMEOUT); - if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) { - invocation.setObjectAttachment(TIMEOUT_KEY, timeout); // pass timeout to remote server - } - } else { - TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countdown; - timeout = (int) timeoutCountDown.timeRemaining(TimeUnit.MILLISECONDS); - invocation.setObjectAttachment(TIMEOUT_KEY, timeout);// pass timeout to remote server - } + int timeout = calculateTimeout(invocation, methodName); if (isOneway) { boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false); currentClient.send(inv, isSent); @@ -172,4 +161,20 @@ public class DubboInvoker extends AbstractInvoker { } } } + + private int calculateTimeout(Invocation invocation, String methodName) { + Object countdown = RpcContext.getContext().get(TIME_COUNTDOWN_KEY); + int timeout = DEFAULT_TIMEOUT; + if (countdown == null) { + timeout = (int) RpcUtils.getTimeout(getUrl(), methodName, RpcContext.getContext(), DEFAULT_TIMEOUT); + if (getUrl().getParameter(ENABLE_TIMEOUT_COUNTDOWN_KEY, false)) { + invocation.setObjectAttachment(TIMEOUT_ATTACHENT_KEY, timeout); // pass timeout to remote server + } + } else { + TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countdown; + timeout = (int) timeoutCountDown.timeRemaining(TimeUnit.MILLISECONDS); + invocation.setObjectAttachment(TIMEOUT_ATTACHENT_KEY, timeout);// pass timeout to remote server + } + return timeout; + } } diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java index 3083e59e8f..a18925d469 100644 --- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java +++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftInvoker.java @@ -64,7 +64,7 @@ public class ThriftInvoker extends AbstractInvoker { } public ThriftInvoker(Class type, URL url, ExchangeClient[] clients, Set> invokers) { - super(type, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY, TIMEOUT_KEY}); + super(type, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY}); this.clients = clients; this.invokers = invokers; }