diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/AbstractRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/CacheableRouterFactory.java similarity index 87% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/AbstractRouterFactory.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/CacheableRouterFactory.java index 18c7ecc7ae8..67b3d412349 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/AbstractRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/CacheableRouterFactory.java @@ -22,10 +22,10 @@ import java.util.concurrent.ConcurrentMap; /** - * If you want to provide a Router implementation based on design of v2.7.0, please extend from this abstract class. - * For 2.6.x style Router, please implement and use RouterFactory directly. + * If you want to provide a router implementation based on design of v2.7.0, please extend from this abstract class. + * For 2.6.x style router, please implement and use RouterFactory directly. */ -public abstract class AbstractRouterFactory implements RouterFactory { +public abstract class CacheableRouterFactory implements RouterFactory { private ConcurrentMap routerMap = new ConcurrentHashMap<>(); @Override diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java index 46a2c4951ff..5addb8e4911 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java @@ -33,7 +33,7 @@ */ public interface Router extends Comparable { /** - * get the router url. + * Get the router url. * * @return url */ @@ -63,24 +63,26 @@ default void notify(List> invokers) { } /** - * To decide whether this router need to execute every time an RPC comes or should only execute when addresses or rule change. + * To decide whether this router need to execute every time an RPC comes or should only execute when addresses or + * rule change. * - * @return + * @return true if the router need to execute every time. */ boolean isRuntime(); /** - * To decide whether this router should take effect when none of the invoker can match the router rule, which means the {@link #route(List, URL, Invocation)} would be empty. - * Most of time, most router implementation would default this value to false. + * To decide whether this router should take effect when none of the invoker can match the router rule, which + * means the {@link #route(List, URL, Invocation)} would be empty. Most of time, most router implementation would + * default this value to false. * - * @return + * @return true to execute if none of invokers matches the current router */ boolean isForce(); /** - * used to sort routers. + * Router's priority, used to sort routers. * - * @return + * @return router's priority */ int getPriority(); } 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 b3707448951..9681ea3f131 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 @@ -27,13 +27,12 @@ import java.util.stream.Collectors; /** - * + * Router chain */ public class RouterChain { // full list of addresses from registry, classified by method name. private List> invokers = Collections.emptyList(); - private URL url; // containing all routers, reconstruct every time 'route://' urls change. private volatile List routers = Collections.emptyList(); @@ -47,8 +46,6 @@ public static RouterChain buildChain(URL url) { } private RouterChain(URL url) { - this.url = url; - List extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class) .getActivateExtension(url, (String[]) null); @@ -74,9 +71,10 @@ public void addRouter(Router router) { } /** - * If we use route:// protocol in version before 2.7.0, each URL will generate a Router instance, - * so we should keep the routers up to date, that is, each time router URLs changes, we should update the routers list, - * only keep the builtinRouters which are available all the time and the latest notified routers which are generated from URLs. + * If we use route:// protocol in version before 2.7.0, each URL will generate a Router instance, so we should + * keep the routers up to date, that is, each time router URLs changes, we should update the routers list, only + * keep the builtinRouters which are available all the time and the latest notified routers which are generated + * from URLs. * * @param routers routers from 'router://' rules in 2.6.x or before. */ @@ -87,9 +85,6 @@ public void addRouters(List routers) { newRouters.addAll(routers); this.routers = newRouters; this.sort(); - /* if (invokers != null) { - this.rebuild(invokers, url, null); - }*/ } private void sort() { @@ -105,9 +100,6 @@ private void sort() { public List> route(URL url, Invocation invocation) { List> finalInvokers = invokers; for (Router router : routers) { -// if (router.isRuntime()) { -// finalInvokers = router.route(finalInvokers, url, invocation); -// } finalInvokers = router.route(finalInvokers, url, invocation); } return finalInvokers; diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java index 13dbbd78ff7..b7644b3459d 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterFactory.java @@ -27,19 +27,20 @@ * * @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory) * @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation) - * - * Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance for each service. - * See {@link AbstractRouterFactory} and {@link RouterChain} for how to extend a new Router or how the Router instances are loaded. + *

+ * Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance + * for each service. See {@link CacheableRouterFactory} and {@link RouterChain} for how to extend a new Router or how + * the Router instances are loaded. */ @SPI public interface RouterFactory { /** * Create router. - * Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's keeped only for compatibility. + * Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility. * - * @param url - * @return router + * @param url url + * @return router instance */ @Adaptive("protocol") Router getRouter(URL url); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java index 83471417e69..bffa1d628ad 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java @@ -32,28 +32,29 @@ import java.util.Map; /** - * + * Config parser */ public class ConfigParser { public static List parseConfigurators(String rawConfig) { List urls = new ArrayList<>(); - ConfiguratorConfig configuratorConfig = parseObject(rawConfig, ConfiguratorConfig.class); + ConfiguratorConfig configuratorConfig = parseObject(rawConfig); String scope = configuratorConfig.getScope(); List items = configuratorConfig.getConfigs(); if (ConfiguratorConfig.SCOPE_APPLICATION.equals(scope)) { items.forEach(item -> urls.addAll(appItemToUrls(item, configuratorConfig))); - } else { // servcie scope by default. + } else { + // service scope by default. items.forEach(item -> urls.addAll(serviceItemToUrls(item, configuratorConfig))); } return urls; } - public static T parseObject(String rawConfig, Class clazz) { - Constructor constructor = new Constructor(clazz); - TypeDescription itemDescription = new TypeDescription(clazz); + private static T parseObject(String rawConfig) { + Constructor constructor = new Constructor(ConfiguratorConfig.class); + TypeDescription itemDescription = new TypeDescription(ConfiguratorConfig.class); itemDescription.addPropertyParameters("items", ConfigItem.class); constructor.addTypeDescription(itemDescription); @@ -63,13 +64,7 @@ public static T parseObject(String rawConfig, Class clazz) { private static List serviceItemToUrls(ConfigItem item, ConfiguratorConfig config) { List urls = new ArrayList<>(); - List addresses = item.getAddresses(); - if (addresses == null) { - addresses = new ArrayList<>(); - } - if (addresses.size() == 0) { - addresses.add(Constants.ANYHOST_VALUE); - } + List addresses = parseAddresses(item); addresses.forEach(addr -> { StringBuilder urlBuilder = new StringBuilder(); @@ -78,12 +73,7 @@ private static List serviceItemToUrls(ConfigItem item, ConfiguratorConfig c urlBuilder.append(appendService(config.getKey())); urlBuilder.append(toParameterString(item)); - urlBuilder.append("&enabled="); - if (item.getType() == null || ConfigItem.GENERAL_TYPE.equals(item.getType())) { - urlBuilder.append(config.getEnabled()); - } else { - urlBuilder.append(item.getEnabled()); - } + parseEnabled(item, config, urlBuilder); urlBuilder.append("&category=").append(Constants.DYNAMIC_CONFIGURATORS_CATEGORY); urlBuilder.append("&configVersion=").append(config.getConfigVersion()); @@ -91,7 +81,7 @@ private static List serviceItemToUrls(ConfigItem item, ConfiguratorConfig c List apps = item.getApplications(); if (apps != null && apps.size() > 0) { apps.forEach(app -> { - urls.add(URL.valueOf(urlBuilder.append("&application=" + app).toString())); + urls.add(URL.valueOf(urlBuilder.append("&application=").append(app).toString())); }); } else { urls.add(URL.valueOf(urlBuilder.toString())); @@ -103,13 +93,7 @@ private static List serviceItemToUrls(ConfigItem item, ConfiguratorConfig c private static List appItemToUrls(ConfigItem item, ConfiguratorConfig config) { List urls = new ArrayList<>(); - List addresses = item.getAddresses(); - if (addresses == null) { - addresses = new ArrayList<>(); - } - if (addresses.size() == 0) { - addresses.add(Constants.ANYHOST_VALUE); - } + List addresses = parseAddresses(item); for (String addr : addresses) { StringBuilder urlBuilder = new StringBuilder(); urlBuilder.append("override://").append(addr).append("/"); @@ -126,12 +110,7 @@ private static List appItemToUrls(ConfigItem item, ConfiguratorConfig confi urlBuilder.append("&application=").append(config.getKey()); - urlBuilder.append("&enabled="); - if (item.getType() == null || ConfigItem.GENERAL_TYPE.equals(item.getType())) { - urlBuilder.append(config.getEnabled()); - } else { - urlBuilder.append(item.getEnabled()); - } + parseEnabled(item, config, urlBuilder); urlBuilder.append("&category=").append(Constants.APP_DYNAMIC_CONFIGURATORS_CATEGORY); urlBuilder.append("&configVersion=").append(config.getConfigVersion()); @@ -152,7 +131,8 @@ private static String toParameterString(ConfigItem item) { } Map parameters = item.getParameters(); if (parameters == null || parameters.isEmpty()) { - throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter you want to change in the rule!"); + throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter " + + "you want to change in the rule."); } parameters.forEach((k, v) -> { @@ -175,13 +155,14 @@ private static String toParameterString(ConfigItem item) { private static String appendService(String serviceKey) { StringBuilder sb = new StringBuilder(); if (StringUtils.isEmpty(serviceKey)) { - throw new IllegalStateException("service field in coniguration is null!"); + throw new IllegalStateException("service field in configuration is null."); } + String interfaceName = serviceKey; int i = interfaceName.indexOf("/"); if (i > 0) { sb.append("group="); - sb.append(interfaceName.substring(0, i)); + sb.append(interfaceName, 0, i); sb.append("&"); interfaceName = interfaceName.substring(i + 1); @@ -198,4 +179,23 @@ private static String appendService(String serviceKey) { return sb.toString(); } + private static void parseEnabled(ConfigItem item, ConfiguratorConfig config, StringBuilder urlBuilder) { + urlBuilder.append("&enabled="); + if (item.getType() == null || ConfigItem.GENERAL_TYPE.equals(item.getType())) { + urlBuilder.append(config.getEnabled()); + } else { + urlBuilder.append(item.getEnabled()); + } + } + + private static List parseAddresses(ConfigItem item) { + List addresses = item.getAddresses(); + if (addresses == null) { + addresses = new ArrayList<>(); + } + if (addresses.size() == 0) { + addresses.add(Constants.ANYHOST_VALUE); + } + return addresses; + } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java index d19e90fad69..da4bd7c37eb 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java @@ -26,7 +26,6 @@ public abstract class AbstractRouter implements Router { protected int priority; protected boolean force = false; - protected boolean enabled = true; protected URL url; protected DynamicConfiguration configuration; @@ -71,14 +70,6 @@ public int compareTo(Router o) { return (this.getPriority() >= o.getPriority()) ? 1 : -1; } - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - public int getPriority() { return priority; } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java index 0cc3da6172c..434ef8cb23b 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java @@ -44,14 +44,18 @@ * */ public class ConditionRouter extends AbstractRouter implements Comparable { - public static final String NAME = "CONDITION_ROUTER"; + public static final String NAME = "condition"; + private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class); protected static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)"); protected Map whenCondition; protected Map thenCondition; - public ConditionRouter(String rule, boolean force) { + private boolean enabled; + + public ConditionRouter(String rule, boolean force, boolean enabled) { this.force = force; + this.enabled = enabled; this.init(rule); } @@ -59,6 +63,7 @@ public ConditionRouter(URL url) { this.url = url; this.priority = url.getParameter(Constants.PRIORITY_KEY, 0); this.force = url.getParameter(Constants.FORCE_KEY, false); + this.enabled = url.getParameter(Constants.ENABLED_KEY, true); init(url.getParameterAndDecoded(Constants.RULE_KEY)); } @@ -154,7 +159,7 @@ else if (",".equals(separator)) { // Should be separated by ',' @Override public List> route(List> invokers, URL url, Invocation invocation) throws RpcException { - if (!isEnabled()) { + if (!enabled) { return invokers; } @@ -194,11 +199,6 @@ public boolean isRuntime() { return this.url.getParameter(Constants.RUNTIME_KEY, false); } - @Override - public boolean isEnabled() { - return url == null ? enabled : url.getParameter(Constants.ENABLED_KEY, true); - } - @Override public URL getUrl() { return url; diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppConfigConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppConfigConditionRouter.java deleted file mode 100644 index b580d3656a4..00000000000 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppConfigConditionRouter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.dubbo.rpc.cluster.router.condition.config; - -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.configcenter.ConfigChangeEvent; -import org.apache.dubbo.configcenter.DynamicConfiguration; - -/** - * - */ -public class AppConfigConditionRouter extends AbstractConfigConditionRouter { - - public AppConfigConditionRouter(DynamicConfiguration configuration, URL url) { - super(configuration, url); - } - - protected synchronized void init() { - String appKey = url.getParameter(Constants.APPLICATION_KEY) + Constants.ROUTERS_SUFFIX; - String appRawRule = configuration.getConfig(appKey); - if (appRawRule != null) { - this.process(new ConfigChangeEvent(appKey, appRawRule)); - } - - configuration.addListener(appKey, this); - } - -} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppConfigConditionRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java similarity index 66% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppConfigConditionRouterFactory.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java index bc62bcb1720..e9276b6a526 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppConfigConditionRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouter.java @@ -16,21 +16,17 @@ */ package org.apache.dubbo.rpc.cluster.router.condition.config; +import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.configcenter.DynamicConfiguration; -import org.apache.dubbo.rpc.cluster.AbstractAppRouterFactory; -import org.apache.dubbo.rpc.cluster.Router; /** - * + * Application level router, "application.routers" */ -@Activate(order = 200) -public class AppConfigConditionRouterFactory extends AbstractAppRouterFactory { - public static final String NAME = "app-config-condition"; +public class AppRouter extends ListenableRouter { + public static final String NAME = "APP_ROUTER"; - @Override - protected Router createRouter(URL url) { - return new AppConfigConditionRouter(DynamicConfiguration.getDynamicConfiguration(), url); + public AppRouter(DynamicConfiguration configuration, URL url) { + super(configuration, url, url.getParameter(Constants.APPLICATION_KEY)); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/AbstractAppRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java similarity index 67% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/AbstractAppRouterFactory.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java index 96d339a6fb1..b55cdbfc8e7 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/AbstractAppRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AppRouterFactory.java @@ -14,14 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.rpc.cluster; +package org.apache.dubbo.rpc.cluster.router.condition.config; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.configcenter.DynamicConfiguration; +import org.apache.dubbo.rpc.cluster.Router; +import org.apache.dubbo.rpc.cluster.RouterFactory; /** - * + * Application level router factory */ -public abstract class AbstractAppRouterFactory implements RouterFactory { +@Activate(order = 200) +public class AppRouterFactory implements RouterFactory { + public static final String NAME = "app"; + private Router router; @Override @@ -37,5 +44,7 @@ public Router getRouter(URL url) { return router; } - protected abstract Router createRouter(URL url); + private Router createRouter(URL url) { + return new AppRouter(DynamicConfiguration.getDynamicConfiguration(), url); + } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AbstractConfigConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java similarity index 79% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AbstractConfigConditionRouter.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java index c5edababfc2..f3dedde7dc3 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/AbstractConfigConditionRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ListenableRouter.java @@ -16,9 +16,11 @@ */ package org.apache.dubbo.rpc.cluster.router.condition.config; +import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.Assert; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.configcenter.ConfigChangeEvent; import org.apache.dubbo.configcenter.ConfigChangeType; @@ -38,26 +40,26 @@ import java.util.List; /** - * + * Abstract router which listens to dynamic configuration */ -public abstract class AbstractConfigConditionRouter extends AbstractRouter implements ConfigurationListener { - public static final String NAME = "CONFIG_CONDITION_OUTER"; +public abstract class ListenableRouter extends AbstractRouter implements ConfigurationListener { + public static final String NAME = "LISTENABLE_ROUTER"; public static final int DEFAULT_PRIORITY = 200; - private static final Logger logger = LoggerFactory.getLogger(AbstractConfigConditionRouter.class); + private static final Logger logger = LoggerFactory.getLogger(ListenableRouter.class); private ConditionRouterRule routerRule; private List conditionRouters = new ArrayList<>(); - public AbstractConfigConditionRouter(DynamicConfiguration configuration, URL url) { + public ListenableRouter(DynamicConfiguration configuration, URL url, String ruleKey) { super(configuration, url); this.force = false; - this.init(); + this.init(ruleKey); } @Override public synchronized void process(ConfigChangeEvent event) { if (logger.isInfoEnabled()) { - logger.info("Notification of condition rule, change type is: " + event.getChangeType() + ", raw rule is:\n " + event - .getValue()); + logger.info("Notification of condition rule, change type is: " + event.getChangeType() + + ", raw rule is:\n " + event.getValue()); } if (event.getChangeType().equals(ConfigChangeType.DELETED)) { @@ -68,8 +70,8 @@ public synchronized void process(ConfigChangeEvent event) { routerRule = ConditionRuleParser.parse(event.getValue()); generateConditions(routerRule, conditionRouters); } catch (Exception e) { - logger.error("Failed to parse the raw condition rule and it will not take effect, please check if the condition rule matches with the template, the raw rule is:\n " + event - .getValue(), e); + logger.error("Failed to parse the raw condition rule and it will not take effect, please check " + + "if the condition rule matches with the template, the raw rule is:\n " + event.getValue(), e); } } } @@ -93,25 +95,11 @@ public int getPriority() { return DEFAULT_PRIORITY; } - /*@Override - public boolean isRuntime() { - return isRuleRuntime(); - }*/ - - @Override - public boolean isEnabled() { - return isRuleEnabled(); - } - @Override public boolean isForce() { return (routerRule != null && routerRule.isForce()); } - private boolean isRuleEnabled() { - return routerRule != null && routerRule.isValid() && routerRule.isEnabled(); - } - private boolean isRuleRuntime() { return routerRule != null && routerRule.isValid() && routerRule.isRuntime(); } @@ -121,8 +109,7 @@ private void generateConditions(ConditionRouterRule rule, List routers.clear(); rule.getConditions().forEach(condition -> { // All sub rules have the same force, runtime value. - ConditionRouter subRouter = new ConditionRouter(condition, rule.isForce()); - subRouter.setEnabled(rule.isEnabled()); + ConditionRouter subRouter = new ConditionRouter(condition, rule.isForce(), rule.isEnabled()); routers.add(subRouter); }); @@ -130,13 +117,21 @@ private void generateConditions(ConditionRouterRule rule, List if (blackWhiteList != null && blackWhiteList.isValid()) { blackWhiteList.getConditions().forEach(condition -> { // All sub rules have the same force, runtime value. - ConditionRouter subRouter = new ConditionRouter(condition, true); - subRouter.setEnabled(blackWhiteList.isEnabled()); + ConditionRouter subRouter = new ConditionRouter(condition, true, blackWhiteList.isEnabled()); routers.add(subRouter); }); } } } - protected abstract void init(); + private void init(String ruleKey) { + Assert.notEmptyString(ruleKey, "router rule's name cannot be null"); + String router = ruleKey + Constants.ROUTERS_SUFFIX; + String rule = configuration.getConfig(router); + if (rule != null) { + this.process(new ConfigChangeEvent(router, rule)); + } + + configuration.addListener(router, this); + } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceConfigConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java similarity index 60% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceConfigConditionRouter.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java index 447973da762..13fd69bccb8 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceConfigConditionRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouter.java @@ -16,28 +16,16 @@ */ package org.apache.dubbo.rpc.cluster.router.condition.config; -import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; -import org.apache.dubbo.configcenter.ConfigChangeEvent; import org.apache.dubbo.configcenter.DynamicConfiguration; /** - * + * Service level router, "server-uniq-name.routers" */ -public class ServiceConfigConditionRouter extends AbstractConfigConditionRouter { +public class ServiceRouter extends ListenableRouter { + public static final String NAME = "SERVICE_ROUTER"; - public ServiceConfigConditionRouter(DynamicConfiguration configuration, URL url) { - super(configuration, url); + public ServiceRouter(DynamicConfiguration configuration, URL url) { + super(configuration, url, url.getEncodedServiceKey()); } - - protected synchronized void init() { - String key = url.getEncodedServiceKey() + Constants.ROUTERS_SUFFIX; - String rawRule = configuration.getConfig(key); - if (rawRule != null) { - this.process(new ConfigChangeEvent(key, rawRule)); - } - - configuration.addListener(key, this); - } - } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceConfigConditionRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java similarity index 79% rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceConfigConditionRouterFactory.java rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java index d16e5a2f6c7..18d4a1dd3e8 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceConfigConditionRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ServiceRouterFactory.java @@ -19,20 +19,20 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.configcenter.DynamicConfiguration; -import org.apache.dubbo.rpc.cluster.AbstractRouterFactory; +import org.apache.dubbo.rpc.cluster.CacheableRouterFactory; import org.apache.dubbo.rpc.cluster.Router; /** - * + * Service level router factory */ @Activate(order = 300) -public class ServiceConfigConditionRouterFactory extends AbstractRouterFactory { +public class ServiceRouterFactory extends CacheableRouterFactory { - public static final String NAME = "config-condition"; + public static final String NAME = "service"; @Override protected Router createRouter(URL url) { - return new ServiceConfigConditionRouter(DynamicConfiguration.getDynamicConfiguration(), url); + return new ServiceRouter(DynamicConfiguration.getDynamicConfiguration(), url); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mock/MockRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mock/MockRouterFactory.java index 238634a9d40..d6f64df2416 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mock/MockRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mock/MockRouterFactory.java @@ -26,10 +26,11 @@ */ @Activate public class MockRouterFactory implements RouterFactory { + public static final String NAME = "mock"; @Override public Router getRouter(URL url) { return new MockInvokersSelector(); } -} \ No newline at end of file +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java index f95573c770a..1776ce69738 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java @@ -120,9 +120,4 @@ public boolean isRuntime() { public boolean isForce() { return url.getParameter(Constants.FORCE_KEY, false); } - - @Override - public boolean isEnabled() { - return url.getParameter(Constants.ENABLED_KEY, false); - } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java index c0dee51b0c4..4edffacd9f2 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java @@ -38,6 +38,9 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import static org.apache.dubbo.common.Constants.FORCE_USE_TAG; +import static org.apache.dubbo.common.Constants.TAG_KEY; + /** * */ @@ -45,7 +48,8 @@ public class TagRouter extends AbstractRouter implements Comparable, Con public static final String NAME = "TAG_ROUTER"; private static final int DEFAULT_PRIORITY = 100; private static final Logger logger = LoggerFactory.getLogger(TagRouter.class); - private static final String TAGROUTERRULES_DATAID = ".tagrouters"; // acts + private static final String RULE_PREFIX = ".tagrouters"; + private TagRouterRule tagRouterRule; private String application; @@ -56,8 +60,8 @@ public TagRouter(DynamicConfiguration configuration, URL url) { @Override public synchronized void process(ConfigChangeEvent event) { if (logger.isDebugEnabled()) { - logger.debug("Notification of tag rule, change type is: " + event.getChangeType() + ", raw rule is:\n " + event - .getValue()); + logger.debug("Notification of tag rule, change type is: " + event.getChangeType() + ", raw rule is:\n " + + event.getValue()); } try { @@ -67,7 +71,8 @@ public synchronized void process(ConfigChangeEvent event) { this.tagRouterRule = TagRuleParser.parse(event.getValue()); } } catch (Exception e) { - logger.error("Failed to parse the raw tag router rule and it will not take effect, please check if the rule matches with the template, the raw rule is:\n ", e); + logger.error("Failed to parse the raw tag router rule and it will not take effect, please check if the " + + "rule matches with the template, the raw rule is:\n ", e); } } @@ -76,15 +81,6 @@ public URL getUrl() { return url; } - /** - * - * @param invokers - * @param url - * @param invocation - * @param - * @return - * @throws RpcException - */ @Override public List> route(List> invokers, URL url, Invocation invocation) throws RpcException { if (CollectionUtils.isEmpty(invokers)) { @@ -92,12 +88,13 @@ public List> route(List> invokers, URL url, Invocation } if (tagRouterRule == null || !tagRouterRule.isValid() || !tagRouterRule.isEnabled()) { - // the invokers must have been preRouted by static tag configuration, so this invoker list is just what we want. return invokers; } List> result = invokers; - String tag = StringUtils.isEmpty(invocation.getAttachment(Constants.TAG_KEY)) ? url.getParameter(Constants.TAG_KEY) : invocation.getAttachment(Constants.TAG_KEY); + String tag = StringUtils.isEmpty(invocation.getAttachment(TAG_KEY)) ? url.getParameter(TAG_KEY) : + invocation.getAttachment(TAG_KEY); + // if we are requesting for a Provider with a specific tag if (StringUtils.isNotEmpty(tag)) { List addresses = tagRouterRule.getTagnameToAddresses().get(tag); @@ -109,13 +106,13 @@ public List> route(List> invokers, URL url, Invocation return result; } } else { - // dynamic tag group doesn't have any item about the requested app OR it's null after filtered by dynamic tag group but force=false. - // check static tag - result = filterInvoker(invokers, invoker -> tag.equals(invoker.getUrl() - .getParameter(Constants.TAG_KEY))); + // dynamic tag group doesn't have any item about the requested app OR it's null after filtered by + // dynamic tag group but force=false. check static tag + result = filterInvoker(invokers, invoker -> tag.equals(invoker.getUrl().getParameter(TAG_KEY))); } - // If there's no tagged providers that can match the current tagged request. force.tag is set by default to false, which means it will invoke any providers without a tag unless it's explicitly disallowed. - if (CollectionUtils.isNotEmpty(result) || Boolean.valueOf(invocation.getAttachment(Constants.FORCE_USE_TAG, url.getParameter(Constants.FORCE_USE_TAG, "false")))) { + // If there's no tagged providers that can match the current tagged request. force.tag is set by default + // to false, which means it will invoke any providers without a tag unless it's explicitly disallowed. + if (CollectionUtils.isNotEmpty(result) || isForceUse(invocation)) { return result; } // FAILOVER: return all Providers without any tags. @@ -123,7 +120,7 @@ public List> route(List> invokers, URL url, Invocation List> tmp = filterInvoker(invokers, invoker -> addressNotMatches(invoker.getUrl(), tagRouterRule .getAddresses())); return filterInvoker(tmp, invoker -> StringUtils.isEmpty(invoker.getUrl() - .getParameter(Constants.TAG_KEY))); + .getParameter(TAG_KEY))); } } else { // List addresses = tagRouterRule.filter(providerApp); @@ -135,10 +132,11 @@ public List> route(List> invokers, URL url, Invocation if (CollectionUtils.isEmpty(result)) { return result; } - // 2. if there are some addresses that are not in any dynamic tag group, continue to filter using the static tag group. + // 2. if there are some addresses that are not in any dynamic tag group, continue to filter using the + // static tag group. } return filterInvoker(result, invoker -> { - String localTag = invoker.getUrl().getParameter(Constants.TAG_KEY); + String localTag = invoker.getUrl().getParameter(TAG_KEY); if (StringUtils.isEmpty(localTag) || !tagRouterRule.getTagNames().contains(localTag)) { return true; } @@ -155,7 +153,6 @@ public int getPriority() { @Override public boolean isRuntime() { return tagRouterRule != null && tagRouterRule.isRuntime(); -// return false; } @Override @@ -164,6 +161,10 @@ public boolean isForce() { return tagRouterRule != null && tagRouterRule.isForce(); } + private boolean isForceUse(Invocation invocation) { + return Boolean.valueOf(invocation.getAttachment(FORCE_USE_TAG, url.getParameter(FORCE_USE_TAG, "false"))); + } + private List> filterInvoker(List> invokers, Predicate> predicate) { return invokers.stream() .filter(predicate) @@ -201,9 +202,9 @@ public void notify(List> invokers) { synchronized (this) { if (!providerApplication.equals(application)) { if (!StringUtils.isEmpty(application)) { - configuration.removeListener(application + TAGROUTERRULES_DATAID, this); + configuration.removeListener(application + RULE_PREFIX, this); } - String key = providerApplication + TAGROUTERRULES_DATAID; + String key = providerApplication + RULE_PREFIX; configuration.addListener(key, this); application = providerApplication; String rawRule = configuration.getConfig(key); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java index a05275806fb..7d3e013123f 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java @@ -19,14 +19,14 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.configcenter.DynamicConfiguration; -import org.apache.dubbo.rpc.cluster.AbstractRouterFactory; +import org.apache.dubbo.rpc.cluster.CacheableRouterFactory; import org.apache.dubbo.rpc.cluster.Router; /** - * + * Tag router factory */ @Activate(order = 100) -public class TagRouterFactory extends AbstractRouterFactory { +public class TagRouterFactory extends CacheableRouterFactory { public static final String NAME = "tag"; diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory index 90dd59f1226..2a807f070ae 100644 --- a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory @@ -1,7 +1,7 @@ file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory script=org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory -configcondition=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceConfigConditionRouterFactory -appconfigcondition=org.apache.dubbo.rpc.cluster.router.condition.config.AppConfigConditionRouterFactory +service=org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouterFactory +app=org.apache.dubbo.rpc.cluster.router.condition.config.AppRouterFactory tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory -mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory \ No newline at end of file +mock=org.apache.dubbo.rpc.cluster.router.mock.MockRouterFactory