You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/12/12 09:01:38 UTC
[dubbo] branch 3.0 updated: [3.0] Add router fail fast option (#9388)
This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.0 by this push:
new 312dd2b [3.0] Add router fail fast option (#9388)
312dd2b is described below
commit 312dd2b7acc7c365ac330955f3634a2e0bb4c149
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Sun Dec 12 17:01:06 2021 +0800
[3.0] Add router fail fast option (#9388)
---
.../org/apache/dubbo/rpc/cluster/Constants.java | 2 ++
.../org/apache/dubbo/rpc/cluster/RouterChain.java | 23 ++++++++++++++++------
.../registry/integration/DynamicDirectory.java | 18 ++++++++++++++---
3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
index ad9bd0d..c493610 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
@@ -135,4 +135,6 @@ public interface Constants {
* The key of shortestResponseSlidePeriod
*/
String SHORTEST_RESPONSE_SLIDE_PERIOD = "shortestResponseSlidePeriod";
+
+ String SHOULD_FAIL_FAST_KEY = "dubbo.router.should-fail-fast";
}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
index 12e32c7..b4ca2c5 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.cluster;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
@@ -30,6 +31,7 @@ import org.apache.dubbo.rpc.cluster.router.state.BitList;
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
import org.apache.dubbo.rpc.cluster.router.state.StateRouterResult;
+import org.apache.dubbo.rpc.model.ModuleModel;
import java.util.ArrayList;
import java.util.Collections;
@@ -63,12 +65,19 @@ public class RouterChain<T> {
private volatile List<StateRouter<T>> builtinStateRouters = Collections.emptyList();
private volatile List<StateRouter<T>> stateRouters = Collections.emptyList();
+ /**
+ * Should continue route if current router's result is empty
+ */
+ private final boolean shouldFailFast;
+
public static <T> RouterChain<T> buildChain(Class<T> interfaceClass, URL url) {
return new RouterChain<>(interfaceClass, url);
}
private RouterChain(Class<T> interfaceClass, URL url) {
- List<RouterFactory> extensionFactories = url.getOrDefaultApplicationModel().getExtensionLoader(RouterFactory.class)
+ ModuleModel moduleModel = url.getOrDefaultModuleModel();
+
+ List<RouterFactory> extensionFactories = moduleModel.getExtensionLoader(RouterFactory.class)
.getActivateExtension(url, ROUTER_KEY);
List<Router> routers = extensionFactories.stream()
@@ -78,7 +87,7 @@ public class RouterChain<T> {
initWithRouters(routers);
- List<StateRouterFactory> extensionStateRouterFactories = url.getOrDefaultApplicationModel()
+ List<StateRouterFactory> extensionStateRouterFactories = moduleModel
.getExtensionLoader(StateRouterFactory.class)
.getActivateExtension(url, ROUTER_KEY);
@@ -89,6 +98,8 @@ public class RouterChain<T> {
// init state routers
initWithStateRouters(stateRouters);
+
+ this.shouldFailFast = Boolean.parseBoolean(ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
}
/**
@@ -158,7 +169,7 @@ public class RouterChain<T> {
for (StateRouter<T> stateRouter : stateRouters) {
StateRouterResult<Invoker<T>> routeResult = stateRouter.route(resultInvokers, url, invocation, false);
resultInvokers = routeResult.getResult();
- if (resultInvokers.isEmpty()) {
+ if (resultInvokers.isEmpty() && shouldFailFast) {
printRouterSnapshot(url, availableInvokers, invocation);
return BitList.emptyList();
}
@@ -179,7 +190,7 @@ public class RouterChain<T> {
// Copy resultInvokers to a arrayList. BitList not support
RouterResult<Invoker<T>> routeResult = router.route(commonRouterResult, url, invocation, false);
commonRouterResult = routeResult.getResult();
- if (CollectionUtils.isEmpty(commonRouterResult)) {
+ if (CollectionUtils.isEmpty(commonRouterResult) && shouldFailFast) {
printRouterSnapshot(url, availableInvokers, invocation);
return BitList.emptyList();
}
@@ -222,7 +233,7 @@ public class RouterChain<T> {
currentNode.setRouterMessage(routerMessage);
// result is empty, log out
- if (resultInvokers.isEmpty()) {
+ if (resultInvokers.isEmpty() && shouldFailFast) {
return snapshotNode;
}
@@ -248,7 +259,7 @@ public class RouterChain<T> {
currentNode.setRouterMessage(routerMessage);
// result is empty, log out
- if (CollectionUtils.isEmpty(routeResult)) {
+ if (CollectionUtils.isEmpty(routeResult) && shouldFailFast) {
return snapshotNode;
} else {
commonRouterResult = routeResult;
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java
index 9a907d6..65b71a7 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry.integration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -34,10 +35,12 @@ import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.Configurator;
+import org.apache.dubbo.rpc.cluster.Constants;
import org.apache.dubbo.rpc.cluster.RouterChain;
import org.apache.dubbo.rpc.cluster.RouterFactory;
import org.apache.dubbo.rpc.cluster.directory.AbstractDirectory;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
+import org.apache.dubbo.rpc.model.ModuleModel;
import java.util.List;
@@ -107,11 +110,18 @@ public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implement
protected ServiceInstancesChangedListener serviceListener;
+ /**
+ * Should continue route if directory is empty
+ */
+ private final boolean shouldFailFast;
+
public DynamicDirectory(Class<T> serviceType, URL url) {
super(url, true);
- this.cluster = url.getOrDefaultApplicationModel().getExtensionLoader(Cluster.class).getAdaptiveExtension();
- this.routerFactory = url.getOrDefaultApplicationModel().getExtensionLoader(RouterFactory.class).getAdaptiveExtension();
+ ModuleModel moduleModel = url.getOrDefaultModuleModel();
+
+ this.cluster = moduleModel.getExtensionLoader(Cluster.class).getAdaptiveExtension();
+ this.routerFactory = moduleModel.getExtensionLoader(RouterFactory.class).getAdaptiveExtension();
if (serviceType == null) {
throw new IllegalArgumentException("service type is null.");
@@ -130,6 +140,8 @@ public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implement
this.directoryUrl = consumerUrl;
String group = directoryUrl.getGroup("");
this.multiGroup = group != null && (ANY_VALUE.equals(group) || group.contains(","));
+
+ this.shouldFailFast = Boolean.parseBoolean(ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
}
@Override
@@ -165,7 +177,7 @@ public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implement
@Override
public List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) {
- if (forbidden) {
+ if (forbidden && shouldFailFast) {
// 1. No service provider 2. Service providers are disabled
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " +
getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " +