chickenlj closed pull request #1438: [Dubbo- support unit router feature] May 
be a nice feature.
URL: https://github.com/apache/incubator-dubbo/pull/1438
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/.gitignore b/.gitignore
index 7f60d60a3d..aaaed0972b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@ target/
 # system ignore
 .DS_Store
 Thumbs.db
+/default.etcd/
diff --git 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
index 6934069ee9..0e3c5d42c2 100644
--- 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
+++ 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/AbstractDirectory.java
@@ -24,14 +24,20 @@
 import com.alibaba.dubbo.rpc.Invocation;
 import com.alibaba.dubbo.rpc.Invoker;
 import com.alibaba.dubbo.rpc.RpcException;
+import com.alibaba.dubbo.rpc.RpcInvocation;
 import com.alibaba.dubbo.rpc.cluster.Directory;
 import com.alibaba.dubbo.rpc.cluster.Router;
 import com.alibaba.dubbo.rpc.cluster.RouterFactory;
 import com.alibaba.dubbo.rpc.cluster.router.MockInvokersSelector;
+import com.alibaba.dubbo.rpc.cluster.router.unit.UnitRouter;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+
+import static com.alibaba.dubbo.common.utils.StringUtils.containsParseKey;
+import static com.alibaba.dubbo.common.utils.StringUtils.parseQueryString;
 
 /**
  * Abstract implementation of Directory: Invoker list returned from this 
Directory's list method have been filtered by Routers
@@ -46,7 +52,7 @@
 
     private volatile boolean destroyed = false;
 
-    private volatile URL consumerUrl;
+    protected volatile URL consumerUrl;
 
     private volatile List<Router> routers;
 
@@ -108,9 +114,36 @@ protected void setRouters(List<Router> routers) {
         // append mock invoker selector
         routers.add(new MockInvokersSelector());
         Collections.sort(routers);
+
+        /**
+         *  We expect unit router will be executed at last,
+         *  because if the unit router has no match,
+         *  it will return the previous available invokers.
+         */
+
+        if(detectUnitRouter()) {
+            routers.add(new UnitRouter());
+        }
+
         this.routers = routers;
     }
 
+    protected List<Invoker<T>> route(List<Invoker<T>> invokers, String method) 
{
+
+        if(invokers == null || invokers.isEmpty()) return invokers;
+
+        Invocation invocation = new RpcInvocation(method, new Class<?>[0], new 
Object[0]);
+        List<Router> routers = getRouters();
+        if (routers != null) {
+            for (Router router : routers) {
+                if (router.getUrl() != null) {
+                    invokers = router.route(invokers, getConsumerUrl(), 
invocation);
+                }
+            }
+        }
+        return invokers;
+    }
+
     public URL getConsumerUrl() {
         return consumerUrl;
     }
@@ -119,6 +152,50 @@ public void setConsumerUrl(URL consumerUrl) {
         this.consumerUrl = consumerUrl;
     }
 
+    private boolean detectUnitRouter() {
+        String unitKey = url.getParameter(Constants.UNIT_KEY);
+        if((unitKey != null && unitKey.length() > 0)
+                // we check if consumer contains `unit` property
+                || 
containsParseKey(url.getParameterAndDecoded(Constants.REFER_KEY), 
Constants.UNIT_KEY))
+            return true;
+
+        return false;
+    }
+
+    /**
+     * use to find current consumer url.
+     *
+     */
+    public URL parseConsumerUrl(final URL url) {
+
+        String refer, path;
+
+        URL invokerUrl = url.setProtocol(
+                url.getParameter(Constants.REGISTRY_KEY, 
Constants.DEFAULT_REGISTRY))
+                .removeParameter(Constants.REGISTRY_KEY);
+
+        if((refer = invokerUrl.getParameterAndDecoded(Constants.REFER_KEY)) != 
null
+                && refer.length() > 0) {
+
+            Map<String, String> parameters = parseQueryString(refer);
+            parameters.remove(Constants.MONITOR_KEY);
+
+            if(!(Constants.ANY_VALUE).equals(path = 
parameters.remove(Constants.INTERFACE_KEY))){
+                URL consumerUrl = new URL(Constants.CONSUMER_PROTOCOL
+                        , parameters.remove(Constants.REGISTER_IP_KEY), 0
+                        , path  , parameters)
+                        . addParameters(Constants.CATEGORY_KEY
+                                , Constants.CONSUMERS_CATEGORY
+                                , Constants.CHECK_KEY
+                                , String.valueOf(false));
+
+                return consumerUrl;
+            }
+        }
+
+        return url;
+    }
+
     public boolean isDestroyed() {
         return destroyed;
     }
diff --git 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
index ae64aa832b..43b18c8c54 100644
--- 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
+++ 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/directory/StaticDirectory.java
@@ -16,22 +16,37 @@
  */
 package com.alibaba.dubbo.rpc.cluster.directory;
 
+import com.alibaba.dubbo.common.Constants;
 import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.utils.StringUtils;
 import com.alibaba.dubbo.rpc.Invocation;
 import com.alibaba.dubbo.rpc.Invoker;
 import com.alibaba.dubbo.rpc.RpcException;
 import com.alibaba.dubbo.rpc.cluster.Router;
+import com.alibaba.dubbo.rpc.support.RpcUtils;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+
+import static com.alibaba.dubbo.common.utils.StringUtils.parseQueryString;
 
 /**
- * StaticDirectory
- *
+ * StaticDirectory,
+ * support new unit feature.
+ * @author yiji.git...@hotmail.com
  */
 public class StaticDirectory<T> extends AbstractDirectory<T> {
 
     private final List<Invoker<T>> invokers;
 
+    private volatile Map<String, List<Invoker<T>>> methodInvokerMap;
+
     public StaticDirectory(List<Invoker<T>> invokers) {
         this(null, invokers, null);
     }
@@ -49,6 +64,75 @@ public StaticDirectory(URL url, List<Invoker<T>> invokers, 
List<Router> routers)
         if (invokers == null || invokers.isEmpty())
             throw new IllegalArgumentException("invokers == null");
         this.invokers = invokers;
+        this.consumerUrl = parseConsumerUrl(getUrl());
+        this.methodInvokerMap = toMethodInvokerMap(invokers);
+    }
+
+    /**
+     * Transform the invokers list into a mapping relationship with a method
+     */
+    private Map<String,List<Invoker<T>>> toMethodInvokerMap(List<Invoker<T>> 
invokers) {
+
+        Map<String, List<Invoker<T>>> newMethodInvokerMap = new 
HashMap<String, List<Invoker<T>>>();
+        newMethodInvokerMap.put(Constants.ANY_VALUE, invokers);
+
+        if (invokers != null && invokers.size() > 0) {
+            for (Invoker<T> invoker : invokers) {
+                URL invokerUrl = invoker.getUrl();
+                if(invokerUrl != null) {
+                    String parameter = 
invokerUrl.getParameter(Constants.METHODS_KEY);
+                    if (parameter != null && parameter.length() > 0) {
+                        String[] methods = 
Constants.COMMA_SPLIT_PATTERN.split(parameter);
+                        if (methods != null && methods.length > 0) {
+                            for (String method : methods) {
+                                if (method != null && method.length() > 0
+                                        && 
!Constants.ANY_VALUE.equals(method)) {
+                                    List<Invoker<T>> methodInvokers = 
newMethodInvokerMap.get(method);
+                                    if (methodInvokers == null) {
+                                        methodInvokers = new 
ArrayList<Invoker<T>>();
+                                        newMethodInvokerMap.put(method, 
methodInvokers);
+                                    }
+                                    methodInvokers.add(invoker);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        String methods = 
parseQueryString(getUrl().getParameterAndDecoded(Constants.REFER_KEY)).get(Constants.METHODS_KEY);
+        if(methods != null) {
+            String[] serviceMethods = 
Constants.COMMA_SPLIT_PATTERN.split(methods);
+            if (serviceMethods != null && serviceMethods.length > 0) {
+                for (String method : serviceMethods) {
+                    List<Invoker<T>> methodInvokers = 
newMethodInvokerMap.get(method);
+                    if (methodInvokers == null || methodInvokers.isEmpty()) {
+                        methodInvokers = invokers;
+                    }
+                    newMethodInvokerMap.put(method, route(methodInvokers, 
method));
+                }
+            }
+        }
+
+        for (String method : new 
HashSet<String>(newMethodInvokerMap.keySet())) {
+            List<Invoker<T>> methodInvokers = newMethodInvokerMap.get(method);
+
+            Collections.sort(methodInvokers, new Comparator<Invoker<T>>() {
+                @Override
+                public int compare(Invoker<T> provider, Invoker<T> other) {
+                    URL providerUrl = provider.getUrl(), otherUrl = 
other.getUrl();
+                    if(providerUrl != null && otherUrl != null)
+                        return 
providerUrl.toString().compareTo(otherUrl.toString());
+                    if(providerUrl == null && otherUrl == null) return 0;
+                    return -1;
+                }
+            });
+
+            newMethodInvokerMap.put(method, 
Collections.unmodifiableList(methodInvokers));
+        }
+
+        return Collections.unmodifiableMap(newMethodInvokerMap);
     }
 
     @Override
@@ -84,7 +168,21 @@ public void destroy() {
     @Override
     protected List<Invoker<T>> doList(Invocation invocation) throws 
RpcException {
 
-        return invokers;
-    }
+        List<Invoker<T>> invokers = null;
 
+        Map<String, List<Invoker<T>>> localMethodInvokerMap = 
this.methodInvokerMap;
+        if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) 
{
+            String methodName = RpcUtils.getMethodName(invocation);
+            Object[] args = RpcUtils.getArguments(invocation);
+
+            if (invokers == null) {
+                invokers = localMethodInvokerMap.get(methodName);
+            }
+            if (invokers == null) {
+                invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);
+            }
+        }
+
+        return invokers == null ? this.invokers : invokers;
+    }
 }
diff --git 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/condition/ConditionRouter.java
 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/condition/ConditionRouter.java
index 05f1d7136d..cb03efe32c 100644
--- 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/condition/ConditionRouter.java
+++ 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/condition/ConditionRouter.java
@@ -45,12 +45,14 @@
 public class ConditionRouter implements Router, Comparable<Router> {
 
     private static final Logger logger = 
LoggerFactory.getLogger(ConditionRouter.class);
+
     private static Pattern ROUTE_PATTERN = 
Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
-    private final URL url;
-    private final int priority;
-    private final boolean force;
-    private final Map<String, MatchPair> whenCondition;
-    private final Map<String, MatchPair> thenCondition;
+
+    protected final URL url;
+    protected final int priority;
+    protected final boolean force;
+    protected final Map<String, MatchPair> whenCondition;
+    protected final Map<String, MatchPair> thenCondition;
 
     public ConditionRouter(URL url) {
         this.url = url;
@@ -75,7 +77,7 @@ public ConditionRouter(URL url) {
         }
     }
 
-    private static Map<String, MatchPair> parseRule(String rule)
+    public static Map<String, MatchPair> parseRule(String rule)
             throws ParseException {
         Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
         if (StringUtils.isBlank(rule)) {
@@ -188,15 +190,15 @@ public int compareTo(Router o) {
         return this.priority == c.priority ? 
url.toFullString().compareTo(c.url.toFullString()) : (this.priority > 
c.priority ? 1 : -1);
     }
 
-    boolean matchWhen(URL url, Invocation invocation) {
+    public boolean matchWhen(URL url, Invocation invocation) {
         return whenCondition == null || whenCondition.isEmpty() || 
matchCondition(whenCondition, url, null, invocation);
     }
 
-    private boolean matchThen(URL url, URL param) {
+    public boolean matchThen(URL url, URL param) {
         return !(thenCondition == null || thenCondition.isEmpty()) && 
matchCondition(thenCondition, url, param, null);
     }
 
-    private boolean matchCondition(Map<String, MatchPair> condition, URL url, 
URL param, Invocation invocation) {
+    public boolean matchCondition(Map<String, MatchPair> condition, URL url, 
URL param, Invocation invocation) {
         Map<String, String> sample = url.toMap();
         boolean result = false;
         for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
@@ -229,11 +231,11 @@ private boolean matchCondition(Map<String, MatchPair> 
condition, URL url, URL pa
         return result;
     }
 
-    private static final class MatchPair {
+    public static final class MatchPair {
         final Set<String> matches = new HashSet<String>();
         final Set<String> mismatches = new HashSet<String>();
 
-        private boolean isMatch(String value, URL param) {
+        public boolean isMatch(String value, URL param) {
             if (!matches.isEmpty() && mismatches.isEmpty()) {
                 for (String match : matches) {
                     if (UrlUtils.isMatchGlobPattern(match, value, param)) {
diff --git 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouter.java
 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouter.java
new file mode 100644
index 0000000000..34bbf2fcdb
--- /dev/null
+++ 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouter.java
@@ -0,0 +1,135 @@
+package com.alibaba.dubbo.rpc.cluster.router.unit;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.logger.Logger;
+import com.alibaba.dubbo.common.logger.LoggerFactory;
+import com.alibaba.dubbo.common.utils.NetUtils;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.RpcException;
+import com.alibaba.dubbo.rpc.cluster.Router;
+import com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * Support consumers to call the same unit of service priority
+ *
+ * @author yiji.git...@hotmail.com
+ */
+public class UnitRouter extends ConditionRouter implements Router {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(UnitRouter.class);
+
+    /**
+     *  we expect consumer should invoker providers that has same value of 
`unit` property.
+     */
+    public static final URL ROUTER_URL =
+            new URL("condition"
+                    , Constants.ANYHOST_VALUE, 0
+                    , Constants.ANY_VALUE )
+                    . addParameters(
+                         Constants.RULE_KEY, URL.encode("=> unit = $unit & 
methods = $methods")
+                    );
+
+    public UnitRouter() {
+        this(ROUTER_URL);
+    }
+
+    private UnitRouter(URL url) {
+        super(ROUTER_URL);
+    }
+
+    @Override
+    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, 
Invocation invocation)
+            throws RpcException {
+        if (invokers == null || invokers.isEmpty()) {
+            return invokers;
+        }
+        try {
+            if (!matchWhen(url, invocation)) {
+                return invokers;
+            }
+            List<Invoker<T>> result = new ArrayList<Invoker<T>>();
+
+            for (Invoker<T> invoker : invokers) {
+                if (matchThen(invoker.getUrl(), url, invocation)) {
+                    result.add(invoker);
+                }
+            }
+            if (!result.isEmpty()) {
+                return result;
+            }
+        } catch (Throwable t) {
+            logger.error("Failed to execute unit router rule: " + getUrl()
+                    + ", invokers: " + invokers
+                    + ", consumer unit: " + 
url.getParameter(Constants.UNIT_KEY, Constants.DEFAULT_UNIT)
+                    + ", cause: " + t.getMessage(), t);
+        }
+        return invokers;
+    }
+
+    public boolean matchThen(URL url, URL param, Invocation invocation) {
+        return !(thenCondition == null || thenCondition.isEmpty()) && 
matchCondition(thenCondition, url, param, invocation);
+    }
+
+    @Override
+    public boolean matchCondition(Map<String, ConditionRouter.MatchPair> 
condition, URL url, URL param, Invocation invocation) {
+
+        Map<String, String> sample = url.toMap();
+        boolean matched = false;
+        for (Map.Entry<String, ConditionRouter.MatchPair> matchPair : 
condition.entrySet()) {
+            String key = matchPair.getKey();
+            String sampleValue ;
+
+            URL consumerUrl = param == null ? url : param;
+            // check if we are matching provider conditions
+            boolean providerCondition = Constants.METHODS_KEY.equals(key) && 
consumerUrl != url;
+
+            //get real invoked method name from invocation
+            if (invocation != null && (Constants.METHOD_KEY.equals(key) || 
Constants.METHODS_KEY.equals(key))) {
+                sampleValue = invocation.getMethodName();
+
+                if(sampleValue == null) return false;
+
+                if(providerCondition) {
+                    String serviceMethod = sample.get(key);
+                    matched = strictMatch(serviceMethod, sampleValue);
+
+                    if(matched) continue;
+
+                    return false;
+                }
+            }
+
+            sampleValue = sample.get(key);
+            if (sampleValue == null) {
+                sampleValue = sample.get(Constants.DEFAULT_KEY_PREFIX + key);
+            }
+
+            if (!matchPair.getValue().isMatch(sampleValue, consumerUrl)) {
+                return false;
+            }
+            matched = true;
+        }
+        return matched;
+    }
+
+    private boolean strictMatch(String serviceMethod, String invokedMethod){
+
+        if(serviceMethod == null) return false;
+
+        if(serviceMethod.indexOf(Constants.COMMA_SEPARATOR) >= 0) {
+            String[] methods = serviceMethod.split(Constants.COMMA_SEPARATOR);
+            for(String method : methods) {
+                if(method.equals(invokedMethod)) return true;
+            }
+        }
+
+        return serviceMethod.equals(invokedMethod);
+    }
+}
diff --git 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouterFactory.java
 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouterFactory.java
new file mode 100644
index 0000000000..62a005ac8c
--- /dev/null
+++ 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouterFactory.java
@@ -0,0 +1,19 @@
+package com.alibaba.dubbo.rpc.cluster.router.unit;
+
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.rpc.cluster.Router;
+import com.alibaba.dubbo.rpc.cluster.RouterFactory;
+
+
+/**
+ * @author yiji.git...@hotmail.com
+ */
+public class UnitRouterFactory  implements RouterFactory {
+
+    public static final String NAME = "unit";
+
+    public Router getRouter(URL url) {
+        return new UnitRouter();
+    }
+
+}
diff --git 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java
 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java
index 7bc6f30f7f..16c4f84395 100644
--- 
a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java
+++ 
b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ClusterUtils.java
@@ -61,7 +61,6 @@ public static URL mergeUrl(URL remoteUrl, Map<String, String> 
localMap) {
             map.remove(Constants.TRANSPORTER_KEY);
             map.remove(Constants.DEFAULT_KEY_PREFIX + 
Constants.TRANSPORTER_KEY);
         }
-
         if (localMap != null && localMap.size() > 0) {
             map.putAll(localMap);
         }
@@ -88,6 +87,19 @@ public static URL mergeUrl(URL remoteUrl, Map<String, 
String> localMap) {
             if (remoteTimestamp != null && remoteTimestamp.length() > 0) {
                 map.put(Constants.REMOTE_TIMESTAMP_KEY, 
remoteMap.get(Constants.TIMESTAMP_KEY));
             }
+            // Use unit passed from provider side
+            String unit = remoteMap.get(Constants.UNIT_KEY);
+            if (unit != null && unit.length() > 0) {
+                map.put(Constants.UNIT_KEY, unit);
+            }
+            // we don't want consumer unit parameter merged to provider
+            else if(localMap != null
+                    && (localMap.containsKey(Constants.UNIT_KEY))
+                            || 
localMap.containsKey(Constants.DEFAULT_KEY_PREFIX + Constants.UNIT_KEY)){
+                map.remove(Constants.UNIT_KEY);
+                map.remove(Constants.DEFAULT_KEY_PREFIX + Constants.UNIT_KEY);
+            }
+
             // Combine filters and listeners on Provider and Consumer
             String remoteFilter = 
remoteMap.get(Constants.REFERENCE_FILTER_KEY);
             String localFilter = localMap.get(Constants.REFERENCE_FILTER_KEY);
diff --git 
a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.RouterFactory
 
b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.RouterFactory
index 239c6f0b62..fb27fe5d0f 100644
--- 
a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.RouterFactory
+++ 
b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.cluster.RouterFactory
@@ -1,3 +1,4 @@
 file=com.alibaba.dubbo.rpc.cluster.router.file.FileRouterFactory
 script=com.alibaba.dubbo.rpc.cluster.router.script.ScriptRouterFactory
-condition=com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
\ No newline at end of file
+condition=com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
+unit=com.alibaba.dubbo.rpc.cluster.router.unit.UnitRouterFactory
\ No newline at end of file
diff --git 
a/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
 
b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
index 2056017bbd..7ff9913381 100644
--- 
a/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
+++ 
b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/file/FileRouterEngineTest.java
@@ -70,8 +70,8 @@ public void testRouteNotAvailable() {
         if (isScriptUnsupported) return;
         URL url = initUrl("notAvailablerule.javascript");
         initInvocation("method1");
-        initDic(url);
         initInvokers(url, true, false);
+        initDic(url);
 
         MockClusterInvoker<FileRouterEngineTest> sinvoker = new 
MockClusterInvoker<FileRouterEngineTest>(
                 dic, url);
@@ -87,8 +87,8 @@ public void testRouteAvailable() {
         if (isScriptUnsupported) return;
         URL url = initUrl("availablerule.javascript");
         initInvocation("method1");
-        initDic(url);
         initInvokers(url);
+        initDic(url);
 
         MockClusterInvoker<FileRouterEngineTest> sinvoker = new 
MockClusterInvoker<FileRouterEngineTest>(
                 dic, url);
@@ -105,8 +105,8 @@ public void testRouteByMethodName() {
         URL url = initUrl("methodrule.javascript");
         {
             initInvocation("method1");
-            initDic(url);
             initInvokers(url, true, true);
+            initDic(url);
 
             MockClusterInvoker<FileRouterEngineTest> sinvoker = new 
MockClusterInvoker<FileRouterEngineTest>(
                     dic, url);
@@ -118,8 +118,8 @@ public void testRouteByMethodName() {
         }
         {
             initInvocation("method2");
-            initDic(url);
             initInvokers(url, true, true);
+            initDic(url);
             MockClusterInvoker<FileRouterEngineTest> sinvoker = new 
MockClusterInvoker<FileRouterEngineTest>(
                     dic, url);
             for (int i = 0; i < 100; i++) {
diff --git 
a/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouterTest.java
 
b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouterTest.java
new file mode 100644
index 0000000000..adf2fdd982
--- /dev/null
+++ 
b/dubbo-cluster/src/test/java/com/alibaba/dubbo/rpc/cluster/router/unit/UnitRouterTest.java
@@ -0,0 +1,233 @@
+/*
+ * 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 com.alibaba.dubbo.rpc.cluster.router.unit;
+
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.utils.NetUtils;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.RpcInvocation;
+import com.alibaba.dubbo.rpc.cluster.Router;
+import com.alibaba.dubbo.rpc.cluster.router.MockInvoker;
+
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author yiji.git...@hotmail.com
+ */
+public class UnitRouterTest {
+
+    @Test
+    public void testRoute_matchWhen() {
+        Invocation invocation = new RpcInvocation();
+        boolean matchWhen = 
router.matchWhen(URL.valueOf("consumer://1.1.1.1/com.foo.BarService"), 
invocation);
+        Assert.assertEquals(true, matchWhen);
+    }
+
+    @Test
+    public void testRoute_matchFilter() {
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?default.serialization=fastjson"));
+        Invoker<String> invoker2 = new 
MockInvoker<String>(URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new 
MockInvoker<String>(URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                URL.valueOf("consumer://" + NetUtils.getLocalHost() + 
"/com.foo.BarService"), new RpcInvocation());
+
+        // we expect available invokers if nothing mactched
+        Assert.assertEquals(3, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_matchFilter0() {
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(URL.valueOf(
+                
"dubbo://10.20.3.3:20880/com.foo.BarService?default.serialization=fastjson&unit=1"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?unit=2"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService?unit=2"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                URL.valueOf("consumer://" + NetUtils.getLocalHost() + 
"/com.foo.BarService?unit=2"), new RpcInvocation());
+
+        Assert.assertEquals(3, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_methodRoute() {
+        Invocation invocation = new RpcInvocation("getFoo", new Class<?>[0], 
new Object[0]);
+        // More than one methods, mismatch
+        boolean matchWhen = router.matchWhen(
+                
URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=setFoo,getFoo,findFoo"),
 invocation);
+        Assert.assertEquals(true, matchWhen);
+
+        // Exactly one method, match
+        matchWhen = router.matchWhen(
+                
URL.valueOf("consumer://1.1.1.1/com.foo.BarService?methods=getFoo"), 
invocation);
+        Assert.assertEquals(true, matchWhen);
+
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        List<Invoker<String>> fileredInvokers1 = router.route(invokers,
+                URL.valueOf("consumer://" + NetUtils.getLocalHost() + 
"/com.foo.BarService?methods=setFoo,getFoo,findFoo"), invocation);
+        // we expect available invokers if nothing mactched
+        Assert.assertEquals(3, fileredInvokers1.size());
+    }
+
+    @Test
+    public void testRoute_methodRoute0() {
+        Invocation invocation = new RpcInvocation("getFoo", new Class<?>[0], 
new Object[0]);
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?methods=setFoo,getFoo&unit=2"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService?methods=setFoo,getFoo&unit=1"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService?methods=setFoo,getFoo&unit=2"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                
URL.valueOf("consumer://127.0.0.1/com.foo.BarService?methods=setFoo,getFoo,findFoo&unit=2"),
 invocation);
+
+        Assert.assertEquals(2, filteredInvokers.size());
+        Assert.assertEquals(invoker1.getUrl(), 
filteredInvokers.get(0).getUrl());
+        Assert.assertEquals(invoker3.getUrl(), 
filteredInvokers.get(1).getUrl());
+    }
+
+    @Test
+    public void testRoute_methodRoute1() {
+        Invocation invocation = new RpcInvocation("getFoo", new Class<?>[0], 
new Object[0]);
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?methods=setFoo,getFoo&unit=2"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService?methods=setFoo,getFoo&unit=1"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService?methods=setFoo,getFoo&unit=2"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        // consumer have not unit value, we expect find all available invokers
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                
URL.valueOf("consumer://127.0.0.1/com.foo.BarService?methods=setFoo,getFoo,findFoo"),
 invocation);
+
+        Assert.assertEquals(3, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_methodRoute2() {
+        Invocation invocation = new RpcInvocation("getFoo", new Class<?>[0], 
new Object[0]);
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?methods=setFoo,getFoo"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService?methods=setFoo,getFoo"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService?methods=setFoo,getFoo"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        // consumer have unit value but service does't have, we expect find 
all available invokers
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                
URL.valueOf("consumer://127.0.0.1/com.foo.BarService?methods=setFoo,getFoo,findFoo&unit=1"),
 invocation);
+
+        Assert.assertEquals(3, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_methodRoute3() {
+        Invocation invocation = new RpcInvocation("getFoo", new Class<?>[0], 
new Object[0]);
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?methods=setFoo,getFoo"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService?methods=setFoo&unit=1"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService?methods=setFoo,getFoo&unit=1"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        // consumer have unit value but service does't have, we expect find 
all available invokers
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                
URL.valueOf("consumer://127.0.0.1/com.foo.BarService?methods=setFoo,getFoo,findFoo&unit=1"),
 invocation);
+
+        Assert.assertEquals(1, filteredInvokers.size());
+        Assert.assertEquals(invoker3.getUrl(), 
filteredInvokers.get(0).getUrl());
+    }
+
+    @Test
+    public void testRoute_methodRoute4() {
+        Invocation invocation = new RpcInvocation(null, new Class<?>[0], new 
Object[0]);
+        // Test filter condition
+        List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
+        Invoker<String> invoker1 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService?methods=setFoo,getFoo"));
+        Invoker<String> invoker2 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService?methods=setFoo,getFoo&unit=1"));
+        Invoker<String> invoker3 = new MockInvoker<String>(
+                
URL.valueOf("dubbo://10.20.3.5:20880/com.foo.BarService?methods=setFoo,getFoo"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+
+        // consumer have unit value but service does't have, we expect find 
all available invokers
+        List<Invoker<String>> filteredInvokers = router.route(invokers,
+                
URL.valueOf("consumer://127.0.0.1/com.foo.BarService?methods=setFoo,getFoo,findFoo&unit=1"),
 invocation);
+
+        // we mock method name is null, we expect all available invokers
+        Assert.assertEquals(3, filteredInvokers.size());
+    }
+
+    UnitRouter router = (UnitRouter)new UnitRouterFactory().getRouter(null);
+
+}
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java 
b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
index 55e86d0382..42a540baa9 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
@@ -633,6 +633,12 @@
 
     public static final boolean DEFAULT_HESSIAN_OVERLOAD_METHOD = false;
 
+    public static final String HOST_KEY = "host";
+
+    public static final String UNIT_KEY = "unit";
+
+    public static final String DEFAULT_UNIT = "global";
+
     public static final String MULTICAST = "multicast";
 
     /*
diff --git 
a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java 
b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java
index faf349f801..4ec6e38b05 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/utils/StringUtils.java
@@ -332,6 +332,22 @@ public static String join(Collection<String> coll, String 
split) {
         return map;
     }
 
+    private static boolean parseKeyValuePair(String str, String itemSeparator, 
String key) {
+        String[] tmp = str.split(itemSeparator);
+        String defaultKey = key != null
+                                &&  
!key.startsWith(Constants.DEFAULT_KEY_PREFIX)
+                            ? Constants.DEFAULT_KEY_PREFIX + key
+                            : key;
+        for (int i = 0; i < tmp.length; i++) {
+            Matcher matcher = KVP_PATTERN.matcher(tmp[i]);
+            if (matcher.matches() == false)
+                continue;
+            String matchedKey = matcher.group(1);
+            if(matchedKey.equals(key) || matchedKey.equals(defaultKey)) return 
true;
+        }
+        return false;
+    }
+
     public static String getQueryStringValue(String qs, String key) {
         Map<String, String> map = StringUtils.parseQueryString(qs);
         return map.get(key);
@@ -349,6 +365,16 @@ public static String getQueryStringValue(String qs, String 
key) {
         return parseKeyValuePair(qs, "\\&");
     }
 
+    /**
+     * parse query string to Parameters then test if contains key,
+     * it more efficient.
+     */
+    public static boolean containsParseKey(String qs, String key) {
+        if (qs == null || qs.length() == 0)
+            return false;
+        return parseKeyValuePair(qs, "\\&", key);
+    }
+
     public static String getServiceKey(Map<String, String> ps) {
         StringBuilder buf = new StringBuilder();
         String group = ps.get(Constants.GROUP_KEY);
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
 
b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
index a42d07c109..a9662c46a7 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
@@ -102,6 +102,9 @@
     // the scope for referring/exporting a service, if it's local, it means 
searching in current JVM only.
     private String scope;
 
+    // current unit (or datacenter) name
+    private String unit;
+
     protected void checkRegistry() {
         // for backward compatibility
         if (registries == null || registries.isEmpty()) {
@@ -514,4 +517,11 @@ public void setScope(String scope) {
         this.scope = scope;
     }
 
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
 }
\ No newline at end of file
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd 
b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 4efbc585ab..0eb9bb1b11 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -162,6 +162,12 @@
                             <![CDATA[ Defines the service visibility, 
choise:[local remote]. default is remote, which can be invoked by network。  
]]></xsd:documentation>
                     </xsd:annotation>
                 </xsd:attribute>
+                <xsd:attribute name="unit" type="xsd:string" use="optional">
+                    <xsd:annotation>
+                        <xsd:documentation>
+                            <![CDATA[ Defines the service and reference unit. 
default is global, we suggest service and reference unit should same. 
]]></xsd:documentation>
+                    </xsd:annotation>
+                </xsd:attribute>
             </xsd:extension>
         </xsd:complexContent>
     </xsd:complexType>
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
index e832daec50..c696862e63 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
@@ -440,19 +440,6 @@ private URL mergeUrl(URL providerUrl) {
         return providerUrl;
     }
 
-    private List<Invoker<T>> route(List<Invoker<T>> invokers, String method) {
-        Invocation invocation = new RpcInvocation(method, new Class<?>[0], new 
Object[0]);
-        List<Router> routers = getRouters();
-        if (routers != null) {
-            for (Router router : routers) {
-                if (router.getUrl() != null) {
-                    invokers = router.route(invokers, getConsumerUrl(), 
invocation);
-                }
-            }
-        }
-        return invokers;
-    }
-
     /**
      * Transform the invokers list into a mapping relationship with a method
      *
diff --git 
a/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java
 
b/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java
index 3463407f92..39143bae6a 100644
--- 
a/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java
+++ 
b/dubbo-registry/dubbo-registry-default/src/test/java/com/alibaba/dubbo/registry/dubbo/RegistryDirectoryTest.java
@@ -57,15 +57,12 @@
     String service = DemoService.class.getName();
     RpcInvocation invocation = new RpcInvocation();
     URL noMeaningUrl = URL.valueOf("notsupport:/" + service + "?refer=" + 
URL.encode("interface=" + service));
-    URL SERVICEURL = URL.valueOf("dubbo://127.0.0.1:9091/" + service + 
"?lazy=true&side=consumer");
+    URL SERVICEURL1 = URL.valueOf("dubbo://127.0.0.1:9091/" + service + 
"?lazy=true&side=consumer");
     URL SERVICEURL2 = URL.valueOf("dubbo://127.0.0.1:9092/" + service + 
"?lazy=true&side=consumer");
     URL SERVICEURL3 = URL.valueOf("dubbo://127.0.0.1:9093/" + service + 
"?lazy=true&side=consumer");
+    URL SERVICEURL4 = URL.valueOf("dubbo://127.0.0.1:9094/" + service + 
"?lazy=true&side=consumer");
     URL SERVICEURL_DUBBO_NOPATH = URL.valueOf("dubbo://127.0.0.1:9092" + 
"?lazy=true&side=consumer");
 
-    @Before
-    public void setUp() {
-    }
-
     private RegistryDirectory getRegistryDirectory(URL url) {
         RegistryDirectory registryDirectory = new RegistryDirectory(URL.class, 
url);
         registryDirectory.setProtocol(protocol);
@@ -148,7 +145,7 @@ public void testNotified_WithError() {
         // ignore error log
         URL badurl = URL.valueOf("notsupported://127.0.0.1/" + service);
         serviceUrls.add(badurl);
-        serviceUrls.add(SERVICEURL);
+        serviceUrls.add(SERVICEURL1);
 
         registryDirectory.notify(serviceUrls);
         Assert.assertEquals(true, registryDirectory.isAvailable());
@@ -160,8 +157,8 @@ public void testNotified_WithError() {
     public void testNotified_WithDuplicateUrls() {
         List<URL> serviceUrls = new ArrayList<URL>();
         // ignore error log
-        serviceUrls.add(SERVICEURL);
-        serviceUrls.add(SERVICEURL);
+        serviceUrls.add(SERVICEURL1);
+        serviceUrls.add(SERVICEURL1);
 
         RegistryDirectory registryDirectory = getRegistryDirectory();
         registryDirectory.notify(serviceUrls);
@@ -218,7 +215,7 @@ private void test_Notified_only_routers(RegistryDirectory 
registryDirectory) {
     private void test_Notified1invokers(RegistryDirectory registryDirectory) {
 
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));// 
.addParameter("refer.autodestroy", "true")
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));// 
.addParameter("refer.autodestroy", "true")
         registryDirectory.notify(serviceUrls);
         Assert.assertEquals(true, registryDirectory.isAvailable());
 
@@ -243,7 +240,7 @@ private void test_Notified1invokers(RegistryDirectory 
registryDirectory) {
     // 2 invokers===================================
     private void test_Notified2invokers(RegistryDirectory registryDirectory) {
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
 
@@ -271,7 +268,7 @@ private void test_Notified2invokers(RegistryDirectory 
registryDirectory) {
     // 3 invoker notifications===================================
     private void test_Notified3invokers(RegistryDirectory registryDirectory) {
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
         serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
 
@@ -300,6 +297,252 @@ private void test_Notified3invokers(RegistryDirectory 
registryDirectory) {
         Assert.assertEquals(1, invokers.size());
     }
 
+    @Test
+    public void test_unit_router_with_available_invokers() {
+
+        URL consumerUrl = new URL(Constants.CONSUMER_PROTOCOL, service, 0, 
service )
+                                  .addParameters(Constants.CATEGORY_KEY
+                                        , Constants.CONSUMERS_CATEGORY
+                                        , Constants.SIDE_KEY
+                                        , Constants.CONSUMER_SIDE
+                                        , Constants.METHODS_KEY
+                                        , "getXXX1,getXXX2,getXXX3"
+                                        , Constants.UNIT_KEY
+                                        , "beijing");
+
+        URL registryUrl = URL.valueOf("notsupport:/" + service + "?refer=" + 
URL.encode(consumerUrl.toFullString()));
+
+        RegistryDirectory registryDirectory = new 
RegistryDirectory(DemoService.class, registryUrl);
+        registryDirectory.setConsumerUrl(consumerUrl);
+        registryDirectory.setProtocol(protocol);
+
+        List<URL> serviceUrls = new ArrayList<URL>();
+        serviceUrls.add(SERVICEURL1.addParameter("methods", 
"getXXX1").addParameter(Constants.UNIT_KEY, "beijing"));
+        serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2").addParameter(Constants.UNIT_KEY, "beijing"));
+        serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3").addParameter(Constants.UNIT_KEY, "hangzhou"));
+        serviceUrls.add(SERVICEURL4.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+
+        registryDirectory.notify(serviceUrls);
+        Assert.assertEquals(true, registryDirectory.isAvailable());
+
+        invocation = new RpcInvocation();
+
+        List invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX1");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(2, invokers.size());
+
+        invocation.setMethodName("getXXX2");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(1, invokers.size());
+
+        invocation.setMethodName("getXXX3");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(2, invokers.size());
+    }
+
+    @Test
+    public void test_unit_router_with_available_invokers0() {
+
+        URL consumerUrl = new URL(Constants.CONSUMER_PROTOCOL, service, 0, 
service )
+                .addParameters(Constants.CATEGORY_KEY
+                        , Constants.CONSUMERS_CATEGORY
+                        , Constants.SIDE_KEY
+                        , Constants.CONSUMER_SIDE
+                        , Constants.METHODS_KEY
+                        , "getXXX1,getXXX2,getXXX3"
+                        , Constants.UNIT_KEY
+                        , "hangzhou");
+
+        URL registryUrl = URL.valueOf("notsupport:/" + service + "?refer=" + 
URL.encode(consumerUrl.toFullString()));
+
+        RegistryDirectory registryDirectory = new 
RegistryDirectory(DemoService.class, registryUrl);
+        registryDirectory.setConsumerUrl(consumerUrl);
+        registryDirectory.setProtocol(protocol);
+
+        List<URL> serviceUrls = new ArrayList<URL>();
+        serviceUrls.add(SERVICEURL1.addParameter("methods", 
"getXXX1").addParameter(Constants.UNIT_KEY, "beijing"));
+        serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2").addParameter(Constants.UNIT_KEY, "beijing"));
+        serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3").addParameter(Constants.UNIT_KEY, "hangzhou"));
+        serviceUrls.add(SERVICEURL4.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+
+        registryDirectory.notify(serviceUrls);
+        Assert.assertEquals(true, registryDirectory.isAvailable());
+
+        invocation = new RpcInvocation();
+
+        List invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX1");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(1, invokers.size());
+
+        invocation.setMethodName("getXXX2");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(1, invokers.size());
+
+        invocation.setMethodName("getXXX3");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(1, invokers.size());
+    }
+
+    @Test
+    public void test_unit_router_with_available_invokers1() {
+
+        URL consumerUrl = new URL(Constants.CONSUMER_PROTOCOL, service, 0, 
service )
+                .addParameters(Constants.CATEGORY_KEY
+                        , Constants.CONSUMERS_CATEGORY
+                        , Constants.SIDE_KEY
+                        , Constants.CONSUMER_SIDE
+                        , Constants.METHODS_KEY
+                        , "getXXX1,getXXX2,getXXX3");
+
+        URL registryUrl = URL.valueOf("notsupport:/" + service + "?refer=" + 
URL.encode(consumerUrl.toFullString()));
+
+        RegistryDirectory registryDirectory = new 
RegistryDirectory(DemoService.class, registryUrl);
+        registryDirectory.setConsumerUrl(consumerUrl);
+        registryDirectory.setProtocol(protocol);
+
+        List<URL> serviceUrls = new ArrayList<URL>();
+        serviceUrls.add(SERVICEURL1.addParameter("methods", 
"getXXX1").addParameter(Constants.UNIT_KEY, "beijing"));
+        serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2").addParameter(Constants.UNIT_KEY, "beijing"));
+        serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3").addParameter(Constants.UNIT_KEY, "hangzhou"));
+        serviceUrls.add(SERVICEURL4.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+
+        registryDirectory.notify(serviceUrls);
+        Assert.assertEquals(true, registryDirectory.isAvailable());
+
+        invocation = new RpcInvocation();
+
+        List invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX1");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX2");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(3, invokers.size());
+
+        invocation.setMethodName("getXXX3");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(2, invokers.size());
+    }
+
+    @Test
+    public void test_unit_router_with_available_invokers2() {
+
+        URL consumerUrl = new URL(Constants.CONSUMER_PROTOCOL, service, 0, 
service )
+                .addParameters(Constants.CATEGORY_KEY
+                        , Constants.CONSUMERS_CATEGORY
+                        , Constants.SIDE_KEY
+                        , Constants.CONSUMER_SIDE
+                        , Constants.METHODS_KEY
+                        , "getXXX1,getXXX2,getXXX3"
+                        , Constants.UNIT_KEY
+                        , "beijing");
+
+        URL registryUrl = URL.valueOf("notsupport:/" + service + "?refer=" + 
URL.encode(consumerUrl.toFullString()));
+
+        RegistryDirectory registryDirectory = new 
RegistryDirectory(DemoService.class, registryUrl);
+        registryDirectory.setConsumerUrl(consumerUrl);
+        registryDirectory.setProtocol(protocol);
+
+        List<URL> serviceUrls = new ArrayList<URL>();
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
+        serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+        serviceUrls.add(SERVICEURL4.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+
+        registryDirectory.notify(serviceUrls);
+        Assert.assertEquals(true, registryDirectory.isAvailable());
+
+        invocation = new RpcInvocation();
+
+        List invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX1");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX2");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(3, invokers.size());
+
+        invocation.setMethodName("getXXX3");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(2, invokers.size());
+    }
+
+    @Test
+    public void test_unit_router_with_available_invokers3() {
+
+        URL consumerUrl = new URL(Constants.CONSUMER_PROTOCOL, service, 0, 
service )
+                .addParameters(Constants.CATEGORY_KEY
+                        , Constants.CONSUMERS_CATEGORY
+                        , Constants.SIDE_KEY
+                        , Constants.CONSUMER_SIDE
+                        , Constants.METHODS_KEY
+                        , "getXXX4");
+
+        URL registryUrl = URL.valueOf("notsupport:/" + service + "?refer=" + 
URL.encode(consumerUrl.toFullString()));
+
+        RegistryDirectory registryDirectory = new 
RegistryDirectory(DemoService.class, registryUrl);
+        registryDirectory.setConsumerUrl(consumerUrl);
+        registryDirectory.setProtocol(protocol);
+
+        List<URL> serviceUrls = new ArrayList<URL>();
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
+        serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+        serviceUrls.add(SERVICEURL4.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
+
+        registryDirectory.notify(serviceUrls);
+        Assert.assertEquals(true, registryDirectory.isAvailable());
+
+        invocation = new RpcInvocation();
+
+        List invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX1");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(4, invokers.size());
+
+        invocation.setMethodName("getXXX2");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(3, invokers.size());
+
+        invocation.setMethodName("getXXX3");
+        invokers = registryDirectory.list(invocation);
+        Assert.assertEquals(2, invokers.size());
+    }
+
     @Test
     public void testParametersMerge() {
         RegistryDirectory registryDirectory = getRegistryDirectory();
@@ -317,7 +560,7 @@ public void testParametersMerge() {
         // The parameters of the inspection registry need to be cleared
         {
             serviceUrls.clear();
-            serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+            serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
             registryDirectory.notify(serviceUrls);
 
             invocation = new RpcInvocation();
@@ -330,7 +573,7 @@ public void testParametersMerge() {
         // The parameters of the provider for the inspection service need merge
         {
             serviceUrls.clear();
-            serviceUrls.add(SERVICEURL.addParameter("methods", 
"getXXX2").addParameter("key", "provider"));
+            serviceUrls.add(SERVICEURL1.addParameter("methods", 
"getXXX2").addParameter("key", "provider"));
 
             registryDirectory.notify(serviceUrls);
             invocation = new RpcInvocation();
@@ -343,7 +586,7 @@ public void testParametersMerge() {
         // The parameters of the test service query need to be with the 
providermerge.
         {
             serviceUrls.clear();
-            serviceUrls.add(SERVICEURL.addParameter("methods", 
"getXXX3").addParameter("key", "provider"));
+            serviceUrls.add(SERVICEURL1.addParameter("methods", 
"getXXX3").addParameter("key", "provider"));
 
             registryDirectory2.notify(serviceUrls);
             invocation = new RpcInvocation();
@@ -356,7 +599,7 @@ public void testParametersMerge() {
 
         {
             serviceUrls.clear();
-            serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+            serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
             registryDirectory.notify(serviceUrls);
 
             invocation = new RpcInvocation();
@@ -368,7 +611,7 @@ public void testParametersMerge() {
         }
         {
             serviceUrls.clear();
-            serviceUrls.add(SERVICEURL.addParameter(Constants.LOADBALANCE_KEY, 
RoundRobinLoadBalance.NAME));
+            
serviceUrls.add(SERVICEURL1.addParameter(Constants.LOADBALANCE_KEY, 
RoundRobinLoadBalance.NAME));
             registryDirectory2.notify(serviceUrls);
 
             invocation = new RpcInvocation();
@@ -383,7 +626,7 @@ public void testParametersMerge() {
         {
             Assert.assertEquals(null, 
registryDirectory2.getUrl().getParameter("mock"));
             serviceUrls.clear();
-            serviceUrls.add(SERVICEURL.addParameter(Constants.MOCK_KEY, 
"true"));
+            serviceUrls.add(SERVICEURL1.addParameter(Constants.MOCK_KEY, 
"true"));
             registryDirectory2.notify(serviceUrls);
 
             Assert.assertEquals("true", 
registryDirectory2.getUrl().getParameter("mock"));
@@ -398,7 +641,7 @@ public void testDestroy() {
         RegistryDirectory registryDirectory = getRegistryDirectory();
 
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
         serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
 
@@ -476,7 +719,7 @@ public void testDubbo1UrlWithGenericInvocation() {
     public void testParmeterRoute() {
         RegistryDirectory registryDirectory = getRegistryDirectory();
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1.napoli"));
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1.napoli"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1.MORGAN,getXXX2"));
         serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1.morgan,getXXX2,getXXX3"));
 
@@ -510,7 +753,7 @@ public void testEmptyNotifyCauseForbidden() {
             Assert.assertEquals(false, registryDirectory.isAvailable());
         }
 
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
         serviceUrls.add(SERVICEURL3.addParameter("methods", 
"getXXX1,getXXX2,getXXX3"));
 
@@ -575,7 +818,7 @@ public void testNotifyoverrideUrls_beforeInvoker() {
 
         //After pushing two provider, the directory state is restored to true
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("timeout", "1000"));
+        serviceUrls.add(SERVICEURL1.addParameter("timeout", "1000"));
         serviceUrls.add(SERVICEURL2.addParameter("timeout", 
"1000").addParameter("connections", "10"));
 
         registryDirectory.notify(serviceUrls);
@@ -602,7 +845,7 @@ public void testNotifyoverrideUrls_afterInvoker() {
 
         //After pushing two provider, the directory state is restored to true
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("timeout", "1000"));
+        serviceUrls.add(SERVICEURL1.addParameter("timeout", "1000"));
         serviceUrls.add(SERVICEURL2.addParameter("timeout", 
"1000").addParameter("connections", "10"));
 
         registryDirectory.notify(serviceUrls);
@@ -632,7 +875,7 @@ public void testNotifyoverrideUrls_withInvoker() {
         RegistryDirectory registryDirectory = getRegistryDirectory();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.addParameter("timeout", "1000"));
+        durls.add(SERVICEURL1.addParameter("timeout", "1000"));
         durls.add(SERVICEURL2.addParameter("timeout", 
"1000").addParameter("connections", "10"));
         durls.add(URL.valueOf("override://0.0.0.0?timeout=1&connections=5"));
 
@@ -661,7 +904,7 @@ public void testNotifyoverrideUrls_Nouse() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.addParameter("timeout", "1"));//One is the same, 
one is different
+        durls.add(SERVICEURL1.addParameter("timeout", "1"));//One is the same, 
one is different
         durls.add(SERVICEURL2.addParameter("timeout", 
"1").addParameter("connections", "5"));
         registryDirectory.notify(durls);
         List<Invoker<?>> invokers = registryDirectory.list(invocation);
@@ -695,7 +938,7 @@ public void testNofityOverrideUrls_Provider() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140").addParameter("timeout", 
"1").addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE));//One is the 
same, one is different
+        durls.add(SERVICEURL1.setHost("10.20.30.140").addParameter("timeout", 
"1").addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE));//One is the 
same, one is different
         durls.add(SERVICEURL2.setHost("10.20.30.141").addParameter("timeout", 
"2").addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE));
         registryDirectory.notify(durls);
 
@@ -721,7 +964,7 @@ public void testNofityOverrideUrls_Clean1() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140").addParameter("timeout", 
"1"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140").addParameter("timeout", 
"1"));
         registryDirectory.notify(durls);
 
         durls = new ArrayList<URL>();
@@ -749,7 +992,7 @@ public void testNofityOverrideUrls_CleanOnly() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140").addParameter("timeout", 
"1"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140").addParameter("timeout", 
"1"));
         registryDirectory.notify(durls);
         Assert.assertEquals(null, 
registryDirectory.getUrl().getParameter("mock"));
 
@@ -784,7 +1027,7 @@ public void testNofityOverrideUrls_CleanNOverride() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140").addParameter("timeout", 
"1"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140").addParameter("timeout", 
"1"));
         registryDirectory.notify(durls);
 
         durls = new ArrayList<URL>();
@@ -808,8 +1051,8 @@ public void testNofityOverrideUrls_disabled_allProvider() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140"));
-        durls.add(SERVICEURL.setHost("10.20.30.141"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140"));
+        durls.add(SERVICEURL1.setHost("10.20.30.141"));
         registryDirectory.notify(durls);
 
         durls = new ArrayList<URL>();
@@ -831,8 +1074,8 @@ public void 
testNofityOverrideUrls_disabled_specifiedProvider() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140"));
-        durls.add(SERVICEURL.setHost("10.20.30.141"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140"));
+        durls.add(SERVICEURL1.setHost("10.20.30.141"));
         registryDirectory.notify(durls);
 
         durls = new ArrayList<URL>();
@@ -860,15 +1103,15 @@ public void testNofity_To_Decrease_provider() {
         invocation = new RpcInvocation();
 
         List<URL> durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140"));
-        durls.add(SERVICEURL.setHost("10.20.30.141"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140"));
+        durls.add(SERVICEURL1.setHost("10.20.30.141"));
         registryDirectory.notify(durls);
 
         List<Invoker<?>> invokers = registryDirectory.list(invocation);
         Assert.assertEquals(2, invokers.size());
 
         durls = new ArrayList<URL>();
-        durls.add(SERVICEURL.setHost("10.20.30.140"));
+        durls.add(SERVICEURL1.setHost("10.20.30.140"));
         registryDirectory.notify(durls);
         List<Invoker<?>> invokers2 = registryDirectory.list(invocation);
         Assert.assertEquals(1, invokers2.size());
@@ -892,8 +1135,8 @@ public void testNofity_disabled_specifiedProvider() {
 
         // Initially disable
         List<URL> durls = new ArrayList<URL>();
-        
durls.add(SERVICEURL.setHost("10.20.30.140").addParameter(Constants.ENABLED_KEY,
 "false"));
-        durls.add(SERVICEURL.setHost("10.20.30.141"));
+        
durls.add(SERVICEURL1.setHost("10.20.30.140").addParameter(Constants.ENABLED_KEY,
 "false"));
+        durls.add(SERVICEURL1.setHost("10.20.30.141"));
         registryDirectory.notify(durls);
 
         List<Invoker<?>> invokers = registryDirectory.list(invocation);
@@ -940,9 +1183,9 @@ public void testNotify_MockProviderOnly() {
         RegistryDirectory registryDirectory = getRegistryDirectory();
 
         List<URL> serviceUrls = new ArrayList<URL>();
-        serviceUrls.add(SERVICEURL.addParameter("methods", "getXXX1"));
+        serviceUrls.add(SERVICEURL1.addParameter("methods", "getXXX1"));
         serviceUrls.add(SERVICEURL2.addParameter("methods", 
"getXXX1,getXXX2"));
-        serviceUrls.add(SERVICEURL.setProtocol(Constants.MOCK_PROTOCOL));
+        serviceUrls.add(SERVICEURL1.setProtocol(Constants.MOCK_PROTOCOL));
 
         registryDirectory.notify(serviceUrls);
         Assert.assertEquals(true, registryDirectory.isAvailable());
@@ -1076,4 +1319,8 @@ public void destroy() {
             }
         }
     }
+
+    @Before
+    public void setUp() {
+    }
 }
diff --git 
a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
 
b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
index 66a8b80367..fbfc358605 100644
--- 
a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
+++ 
b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
@@ -20,8 +20,6 @@
 import com.alibaba.com.caucho.hessian.io.beans.Hessian2StringShortType;
 import com.alibaba.com.caucho.hessian.io.beans.PersonType;
 
-import org.junit.Test;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
@@ -30,9 +28,14 @@
 import java.util.List;
 import java.util.Map;
 
+import org.junit.Test;
+
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertTrue;
 
+/**
+ * @author jason.sh...@hotmail.com
+ */
 public class Hessian2StringShortTest extends SerializeTestBase {
 
     @Test
@@ -126,10 +129,10 @@ public void 
serialize_string_person_map_then_deserialize() throws Exception {
         Hessian2StringShortType stringShort = new Hessian2StringShortType();
         Map<String, PersonType> stringPersonTypeMap = new HashMap<String, 
PersonType>();
         stringPersonTypeMap.put("first", new PersonType(
-                "jason.shang", 26, (double) 0.1, (short)1, (byte)2, 
Arrays.asList((short)1,(short)1)
+            "jason.shang", 26, (double) 0.1, (short)1, (byte)2, 
Arrays.asList((short)1,(short)1)
         ));
         stringPersonTypeMap.put("last", new PersonType(
-                "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, 
Arrays.asList((short)2,(short)2)
+            "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, 
Arrays.asList((short)2,(short)2)
         ));
         stringShort.stringPersonTypeMap = stringPersonTypeMap;
 
@@ -149,11 +152,11 @@ public void 
serialize_string_person_map_then_deserialize() throws Exception {
 
 
         assertEquals(new PersonType(
-                "jason.shang", 26, (double) 0.1, (short)1, (byte)2, 
Arrays.asList((short)1,(short)1)
+            "jason.shang", 26, (double) 0.1, (short)1, (byte)2, 
Arrays.asList((short)1,(short)1)
         ), deserialize.stringPersonTypeMap.get("first"));
 
         assertEquals(new PersonType(
-                "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, 
Arrays.asList((short)2,(short)2)
+            "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, 
Arrays.asList((short)2,(short)2)
         ), deserialize.stringPersonTypeMap.get("last"));
 
     }
diff --git 
a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
 
b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
index 5924b237c0..3d528637de 100644
--- 
a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
+++ 
b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
@@ -23,6 +23,7 @@
  *
  * test short serialize & deserialize model
  *
+ * @author jason.shang
  */
 public class Hessian2StringShortType implements Serializable {
 
diff --git 
a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
 
b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
index 4d3a9ebab6..ac485286b4 100644
--- 
a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
+++ 
b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
@@ -19,6 +19,9 @@
 import java.io.Serializable;
 import java.util.List;
 
+/**
+ * @author jason.shang
+ */
 public class PersonType implements Serializable {
 
     String name;


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@dubbo.apache.org
For additional commands, e-mail: notifications-h...@dubbo.apache.org

Reply via email to