You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2018/08/28 12:26:52 UTC

[incubator-dubbo] 01/02: Add Router name and fix routerchain error.

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit 0e133c59ef53c3a92030881045b23e460e93ad1f
Author: ken.lj <ke...@gmail.com>
AuthorDate: Tue Aug 28 17:24:22 2018 +0800

    Add Router name and fix routerchain error.
---
 .../java/org/apache/dubbo/rpc/cluster/Router.java  |  7 +++
 .../org/apache/dubbo/rpc/cluster/RouterChain.java  | 34 ++++++++++----
 .../rpc/cluster/directory/AbstractDirectory.java   |  2 +-
 .../dubbo/rpc/cluster/router/AbstractRouter.java   | 54 ++++++++++++++++++++++
 ...tionRouterRule.java => AbstractRouterRule.java} | 12 ++---
 .../apache/dubbo/rpc/cluster/router/TreeNode.java  | 12 ++++-
 .../cluster/router/condition/ConditionRouter.java  |  3 +-
 .../condition/config/ConditionRouterRule.java      | 39 ++--------------
 .../condition/config/ConditionRuleParser.java      |  2 +-
 .../condition/config/ConfigConditionRouter.java    | 22 ++++++---
 .../rpc/cluster/router/group/GroupRouter.java      | 39 ++++++++++++----
 .../router/group/model/GroupRouterRule.java        | 17 ++++++-
 .../router/group/{ => model}/GroupRuleParser.java  |  8 ++--
 .../registry/integration/RegistryDirectory.java    |  1 +
 14 files changed, 177 insertions(+), 75 deletions(-)

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 43410b7..a9f2e79 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
@@ -55,6 +55,13 @@ public interface Router extends Comparable<Router> {
         return null;
     }
 
+    default void setRouterChain(RouterChain routerChain) {
+    }
+
+    default String getName() {
+        return "";
+    }
+
     default boolean isRuntime() {
         return true;
     }
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 3305eae..0cf385e 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
@@ -26,25 +26,31 @@ import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.cluster.router.InvokerTreeCache;
 import org.apache.dubbo.rpc.cluster.router.TreeNode;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 /**
  *
  */
 public class RouterChain<T> {
 
-    Map<String, List<Invoker<T>>> fullMethodInvokers;
+    private Map<String, List<Invoker<T>>> fullMethodInvokers;
+    private URL url;
 
     private InvokerTreeCache<T> treeCache;
-
-    List<Router> routers;
+    private List<Router> routers;
 
     public static <T> RouterChain<T> buildChain(DynamicConfiguration dynamicConfiguration) {
+        RouterChain<T> routerChain = new RouterChain<>();
         List<RouterFactory> extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class).getActivateExtension(dynamicConfiguration.getUrl(), (String[]) null);
-        List<Router> routers = extensionFactories.stream().map(factory -> factory.getRouter(dynamicConfiguration)).collect(Collectors.toList());
-        return new RouterChain<>(routers);
+        extensionFactories.stream()
+                .map(factory -> factory.getRouter(dynamicConfiguration))
+                .forEach(router -> {
+                    routerChain.addRouter(router);
+                    router.setRouterChain(routerChain);
+                });
+        return routerChain;
     }
 
     protected RouterChain(List<Router> routers) {
@@ -53,6 +59,7 @@ public class RouterChain<T> {
     }
 
     protected RouterChain() {
+        this.routers = new ArrayList<>();
         treeCache = new InvokerTreeCache<>();
     }
 
@@ -77,7 +84,7 @@ public class RouterChain<T> {
         TreeNode root = treeCache.buildTree();
         Router router = routers.get(0);
         methodInvokers.forEach((method, invokers) -> {
-            TreeNode<T> node = new TreeNode<>("method", method, invokers, true);
+            TreeNode<T> node = new TreeNode<>("METHOD_ROUTER", "method", method, invokers, true);
             root.addChild(node);
             Invocation invocation1 = new RpcInvocation(method, new Class<?>[0], new Object[0]);
             routeeee(router, 1, node, router.preRoute(invokers, url, invocation1), url, invocation1);
@@ -86,7 +93,7 @@ public class RouterChain<T> {
 
     private void routeeee(Router router, int i, TreeNode parentNode, Map<String, List<Invoker<T>>> invokers, URL url, Invocation invocation) {
         invokers.forEach((routerValue, list) -> {
-            TreeNode<T> node = new TreeNode<>(router.getKey(), routerValue, list, router.isForce());
+            TreeNode<T> node = new TreeNode<>(router.getName(), router.getKey(), routerValue, list, router.isForce());
             parentNode.addChild(node);
             // Only when we have more routers and the sub-lis is not empty.
             if (i < routers.size() && CollectionUtils.isNotEmpty(list)) {
@@ -97,7 +104,6 @@ public class RouterChain<T> {
     }
 
     public List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) {
-        // TODO will calculate every time
         List<Invoker<T>> finalInvokers = treeCache.getInvokers(treeCache.getTree(), url, invocation);
         for (Router router : routers) {
             if (router.isRuntime()) {
@@ -107,7 +113,17 @@ public class RouterChain<T> {
         return finalInvokers;
     }
 
+    public void notifyRuleChanged() {
+        preRoute(this.fullMethodInvokers, url, null);
+    }
+
     public void notifyFullInvokers(Map<String, List<Invoker<T>>> invokers, URL url) {
+        setFullMethodInvokers(invokers);
         preRoute(invokers, url, null);
     }
+
+    public void setFullMethodInvokers(Map<String, List<Invoker<T>>> fullMethodInvokers) {
+        this.fullMethodInvokers = fullMethodInvokers;
+        this.url = url;
+    }
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
index 00a4fa1..07e6dd3 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
@@ -72,7 +72,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
 
         try {
             // Get invokers from cache, only runtime routers will be executed.
-            routerChain.route(invokers, getConsumerUrl(), invocation);
+            return routerChain.route(invokers, getConsumerUrl(), invocation);
         } catch (Throwable t) {
             logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
         }
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
new file mode 100644
index 0000000..95abaca
--- /dev/null
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterChain;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * TODO Extract more code here if necessary
+ */
+public abstract class AbstractRouter implements Router {
+    protected RouterChain routerChain;
+
+    @Override
+    public URL getUrl() {
+        return null;
+    }
+
+    @Override
+    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
+        return null;
+    }
+
+    @Override
+    public <T> Map<String, List<Invoker<T>>> preRoute(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
+        return null;
+    }
+
+    @Override
+    public void setRouterChain(RouterChain routerChain) {
+        this.routerChain = routerChain;
+    }
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouterRule.java
similarity index 85%
copy from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java
copy to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouterRule.java
index cdbadc7..4a0c6e4 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouterRule.java
@@ -14,16 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.rpc.cluster.router.condition.config;
+package org.apache.dubbo.rpc.cluster.router;
 
 /**
- *
+ * TODO Extract more code here if necessary
  */
-public class ConditionRouterRule {
+public abstract class AbstractRouterRule {
     private String ruleBody;
-    private boolean runtime;
-    private boolean force;
-    private boolean valid;
+    private boolean runtime = false;
+    private boolean force = false;
+    private boolean valid = true;
 
     public String getRuleBody() {
         return ruleBody;
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/TreeNode.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/TreeNode.java
index 813a0c2..106e244 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/TreeNode.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/TreeNode.java
@@ -28,6 +28,7 @@ import java.util.List;
 public class TreeNode<T> {
     public static final String FAILOVER_KEY = "failover";
 
+    private String routerName;
     private String conditionKey;
     private String conditionValue;
     private boolean force;
@@ -38,7 +39,8 @@ public class TreeNode<T> {
         this.children = new ArrayList<>();
     }
 
-    public TreeNode(String conditionKey, String conditionValue, List<Invoker<T>> invokers, boolean force) {
+    public TreeNode(String routerName, String conditionKey, String conditionValue, List<Invoker<T>> invokers, boolean force) {
+        this.routerName = routerName;
         this.conditionKey = conditionKey;
         this.conditionValue = conditionValue;
         this.invokers = invokers;
@@ -61,6 +63,14 @@ public class TreeNode<T> {
         return false;
     }
 
+    public String getRouterName() {
+        return routerName;
+    }
+
+    public void setRouterName(String routerName) {
+        this.routerName = routerName;
+    }
+
     public String getConditionKey() {
         return conditionKey;
     }
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 a2de676..d596b6c 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
@@ -28,6 +28,7 @@ import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
 import org.apache.dubbo.rpc.cluster.router.TreeNode;
 
 import java.text.ParseException;
@@ -44,7 +45,7 @@ import java.util.regex.Pattern;
  * ConditionRouter
  *
  */
-public class ConditionRouter implements Router, Comparable<Router> {
+public class ConditionRouter extends AbstractRouter implements Comparable<Router> {
 
     private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
     protected static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java
index cdbadc7..1cf3d73 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRouterRule.java
@@ -16,44 +16,11 @@
  */
 package org.apache.dubbo.rpc.cluster.router.condition.config;
 
+import org.apache.dubbo.rpc.cluster.router.AbstractRouterRule;
+
 /**
  *
  */
-public class ConditionRouterRule {
-    private String ruleBody;
-    private boolean runtime;
-    private boolean force;
-    private boolean valid;
-
-    public String getRuleBody() {
-        return ruleBody;
-    }
-
-    public void setRuleBody(String ruleBody) {
-        this.ruleBody = ruleBody;
-    }
-
-    public boolean isRuntime() {
-        return runtime;
-    }
-
-    public void setRuntime(boolean runtime) {
-        this.runtime = runtime;
-    }
-
-    public boolean isForce() {
-        return force;
-    }
-
-    public void setForce(boolean force) {
-        this.force = force;
-    }
-
-    public boolean isValid() {
-        return valid;
-    }
+public class ConditionRouterRule extends AbstractRouterRule {
 
-    public void setValid(boolean valid) {
-        this.valid = valid;
-    }
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRuleParser.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRuleParser.java
index 46eec24..f9bc49f 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRuleParser.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConditionRuleParser.java
@@ -23,7 +23,7 @@ public class ConditionRuleParser {
 
     public static ConditionRouterRule parse(String rawRule) {
         ConditionRouterRule conditionRouterRule = new ConditionRouterRule();
-        conditionRouterRule.setRuleBody("host!=10.20.153.10,10.20.153.11=>");
+        conditionRouterRule.setRuleBody("method!=sayHello => ");
         conditionRouterRule.setValid(true);
         return conditionRouterRule;
     }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java
index 8fbef7b..98c442e 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/config/ConfigConditionRouter.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.config.dynamic.DynamicConfiguration;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.RouterChain;
 import org.apache.dubbo.rpc.cluster.router.TreeNode;
 import org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter;
 
@@ -35,17 +36,14 @@ import java.util.List;
 import java.util.Map;
 
 /**
- *
+ * TODO only support one router rule =>, it will be inconvenient if we want to add more than one rules.
  */
 public class ConfigConditionRouter extends ConditionRouter implements ConfigurationListener {
+    public static final String NAME = "CONFIG_CONDITION_OUTER";
     private static final Logger logger = LoggerFactory.getLogger(ConfigConditionRouter.class);
     private DynamicConfiguration configuration;
     private ConditionRouterRule routerRule;
 
-    public ConfigConditionRouter(URL url) {
-        super(url);
-    }
-
     public ConfigConditionRouter(DynamicConfiguration configuration) {
         this.configuration = configuration;
         this.priority = -2;
@@ -66,6 +64,7 @@ public class ConfigConditionRouter extends ConditionRouter implements Configurat
         try {
             routerRule = ConditionRuleParser.parse(rawRule);
             init(routerRule.getRuleBody());
+            routerChain.notifyRuleChanged();
         } catch (Exception e) {
             logger.error(e);
             // TODO
@@ -76,7 +75,7 @@ public class ConfigConditionRouter extends ConditionRouter implements Configurat
     public <T> Map<String, List<Invoker<T>>> preRoute(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
         Map<String, List<Invoker<T>>> map = new HashMap<>();
 
-        if (CollectionUtils.isEmpty(invokers) || routerRule == null) {
+        if (CollectionUtils.isEmpty(invokers) || routerRule == null || !routerRule.isValid()) {
             return map;
         }
 
@@ -85,12 +84,18 @@ public class ConfigConditionRouter extends ConditionRouter implements Configurat
             return map;
         }
 
+        // only one branch, always use the failover key
         map.put(TreeNode.FAILOVER_KEY, route(invokers, url, invocation));
 
         return map;
     }
 
     @Override
+    public void setRouterChain(RouterChain routerChain) {
+
+    }
+
+    @Override
     public boolean isRuntime() {
         return routerRule != null && routerRule.isValid() && routerRule.isRuntime();
     }
@@ -104,4 +109,9 @@ public class ConfigConditionRouter extends ConditionRouter implements Configurat
     public boolean isForce() {
         return routerRule.isForce();
     }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRouter.java
index 28d2327..724992d 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRouter.java
@@ -31,8 +31,10 @@ import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
 import org.apache.dubbo.rpc.cluster.router.TreeNode;
 import org.apache.dubbo.rpc.cluster.router.group.model.GroupRouterRule;
+import org.apache.dubbo.rpc.cluster.router.group.model.GroupRuleParser;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -44,7 +46,8 @@ import java.util.stream.Collectors;
 /**
  *
  */
-public class GroupRouter implements Router, Comparable<Router>, ConfigurationListener {
+public class GroupRouter extends AbstractRouter implements Comparable<Router>, ConfigurationListener {
+    public static final String NAME = "GROUP_ROUTER";
     private static final Logger logger = LoggerFactory.getLogger(GroupRouter.class);
     private static final String GROUPRULE_DATAID = "global.routers";
     private static final String ROUTE_GROUP = "route.group";
@@ -75,6 +78,7 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
         String rawRule = event.getNewValue();
         // remove, set groupRouterRule to null
         // change, update groupRouterRule
+        routerChain.notifyRuleChanged();
     }
 
     @Override
@@ -91,9 +95,9 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
         String routeGroup = StringUtils.isEmpty(invocation.getAttachment(ROUTE_GROUP)) ? url.getParameter(ROUTE_GROUP) : invocation.getAttachment(ROUTE_GROUP);
         if (StringUtils.isNotEmpty(routeGroup)) {
             String providerApp = invokers.get(0).getUrl().getParameter(Constants.APPLICATION_KEY);
-            List<String> ips = groupRouterRule.filter(routeGroup, providerApp);
-            if (CollectionUtils.isNotEmpty(ips)) {
-                result = filterInvoker(invokers, invoker -> ipMatches(invoker.getUrl(), ips));
+            List<String> addresses = groupRouterRule.filter(routeGroup, providerApp);
+            if (CollectionUtils.isNotEmpty(addresses)) {
+                result = filterInvoker(invokers, invoker -> addressMatches(invoker.getUrl(), addresses));
             } else {
                 result = filterInvoker(invokers, invoker -> invoker.getUrl().getParameter(ROUTE_GROUP).equals(routeGroup));
             }
@@ -108,7 +112,7 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
     public <T> Map<String, List<Invoker<T>>> preRoute(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
         Map<String, List<Invoker<T>>> map = new HashMap<>();
 
-        if (CollectionUtils.isEmpty(invokers)) {
+        if (CollectionUtils.isEmpty(invokers) || groupRouterRule == null || !groupRouterRule.isValid()) {
             return map;
         }
 
@@ -117,9 +121,16 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
             return map;
         }
 
-        // FIXME Consider groupRouterRule
         invokers.forEach(invoker -> {
-            String routeGroup = invoker.getUrl().getParameter(ROUTE_GROUP);
+            String providerApp = invoker.getUrl().getParameter(Constants.APPLICATION_KEY);
+            String address = invoker.getUrl().getAddress();
+            String routeGroup = groupRouterRule.getIpAppToGroup().get(providerApp + address);
+            if (StringUtils.isEmpty(routeGroup)) {
+                routeGroup = invoker.getUrl().getParameter(ROUTE_GROUP);
+            }
+            if (StringUtils.isEmpty(routeGroup)) {
+                routeGroup = TreeNode.FAILOVER_KEY;
+            }
             List<Invoker<T>> subInvokers = map.computeIfAbsent(routeGroup, k -> new ArrayList<>());
             subInvokers.add(invoker);
         });
@@ -128,6 +139,11 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
     }
 
     @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
     public boolean isRuntime() {
         return false;
     }
@@ -136,6 +152,11 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
         return ROUTE_GROUP;
     }
 
+    @Override
+    public boolean isForce() {
+        return false;
+    }
+
     public boolean isRuntime(Invocation invocation) {
         return true;
     }
@@ -146,8 +167,8 @@ public class GroupRouter implements Router, Comparable<Router>, ConfigurationLis
                 .collect(Collectors.toList());
     }
 
-    private boolean ipMatches(URL url, List<String> ips) {
-        return ips.contains(url.getHost());
+    private boolean addressMatches(URL url, List<String> addresses) {
+        return addresses.contains(url.getAddress());
     }
 
     @Override
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRouterRule.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRouterRule.java
index 687a3fb..d434e42 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRouterRule.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRouterRule.java
@@ -16,13 +16,28 @@
  */
 package org.apache.dubbo.rpc.cluster.router.group.model;
 
+import org.apache.dubbo.rpc.cluster.router.AbstractRouterRule;
+
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  *
  */
-public class GroupRouterRule {
+public class GroupRouterRule extends AbstractRouterRule {
+
+    // key: app+address, value: environment
+    private Map<String, String> ipAppToGroup;
+
     public List<String> filter(String routeGroup, String app) {
         return null;
     }
+
+    public Map<String, String> getIpAppToGroup() {
+        //FIXME
+        ipAppToGroup = new HashMap<>();
+        ipAppToGroup.put("demo-provider127.0.0.1", "test1");
+        return ipAppToGroup;
+    }
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRuleParser.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRuleParser.java
similarity index 82%
rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRuleParser.java
rename to dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRuleParser.java
index 8656956..3be756f 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/GroupRuleParser.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/group/model/GroupRuleParser.java
@@ -14,9 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.rpc.cluster.router.group;
-
-import org.apache.dubbo.rpc.cluster.router.group.model.GroupRouterRule;
+package org.apache.dubbo.rpc.cluster.router.group.model;
 
 /**
  *
@@ -24,6 +22,8 @@ import org.apache.dubbo.rpc.cluster.router.group.model.GroupRouterRule;
 public class GroupRuleParser {
 
     public static GroupRouterRule parse(String rawRule) {
-        return null;
+        GroupRouterRule groupRouterRule = new GroupRouterRule();
+        groupRouterRule.setValid(true);
+        return groupRouterRule;
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 1660514..30c14b3 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -366,6 +366,7 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
                 }
                 try {
                     Router router = routerFactory.getRouter(url);
+                    router.setRouterChain(routerChain);
                     if (!routers.contains(router))
                         routers.add(router);
                 } catch (Throwable t) {