beiwei30 closed pull request #2228: [Dubbo- support tag router feature] Add a 
new Router implement -- TagRouter
URL: https://github.com/apache/incubator-dubbo/pull/2228
 
 
   

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/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
new file mode 100644
index 0000000000..38fd6166ef
--- /dev/null
+++ 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
@@ -0,0 +1,109 @@
+/*
+ * 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.tag;
+
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Router;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TagRouter
+ */
+public class TagRouter implements Router, Comparable<Router> {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(TagRouter.class);
+
+    private final int priority;
+    private final URL url;
+
+    public static final URL ROUTER_URL = new URL("tag", 
Constants.ANYHOST_VALUE, 0, 
Constants.ANY_VALUE).addParameters(Constants.RUNTIME_KEY, "true");
+
+    public TagRouter(URL url) {
+        this.url = url;
+        this.priority = url.getParameter(Constants.PRIORITY_KEY, 0);
+    }
+
+    public TagRouter() {
+        this.url = ROUTER_URL;
+        this.priority = url.getParameter(Constants.PRIORITY_KEY, 0);
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    @Override
+    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, 
Invocation invocation) throws RpcException {
+        // filter
+        List<Invoker<T>> result = new ArrayList<>();
+        try {
+            // Dynamic param
+            String tag = 
RpcContext.getContext().getAttachment(Constants.REQUEST_TAG_KEY);
+            // Tag request
+            if (!StringUtils.isEmpty(tag)) {
+                // Select tag invokers first
+                for (Invoker<T> invoker : invokers) {
+                    if 
(tag.equals(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
+                        result.add(invoker);
+                    }
+                }
+                // If no invoker be selected, downgrade to normal invokers
+                if (result.isEmpty()) {
+                    for (Invoker<T> invoker : invokers) {
+                        if 
(StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
+                            result.add(invoker);
+                        }
+                    }
+                }
+            // Normal request
+            } else {
+                for (Invoker<T> invoker : invokers) {
+                    // Can't access tag invoker,only normal invoker should be 
selected
+                    if 
(StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
+                        result.add(invoker);
+                    }
+                }
+            }
+            return result;
+        } catch (Exception e) {
+            logger.error("Route by tag error,return all invokers.", e);
+        }
+        // Downgrade to all invokers
+        return invokers;
+    }
+
+    @Override
+    public int compareTo(Router o) {
+        if (o == null || o.getClass() != TagRouter.class) {
+            return 1;
+        }
+        TagRouter c = (TagRouter) o;
+        return this.priority == c.priority ? 
url.toFullString().compareTo(c.url.toFullString()) : (this.priority > 
c.priority ? 1 : -1);
+    }
+}
diff --git 
a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
new file mode 100644
index 0000000000..05ad427ce6
--- /dev/null
+++ 
b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
@@ -0,0 +1,32 @@
+/*
+ * 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.tag;
+
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterFactory;
+
+public class TagRouterFactory implements RouterFactory {
+
+    public static final String NAME = "tag";
+
+    @Override
+    public Router getRouter(URL url) {
+        return new TagRouter(url);
+    }
+}
diff --git 
a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
 
b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
index 0ada9c3be9..2d4717cfaa 100644
--- 
a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
+++ 
b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
@@ -1,3 +1,4 @@
 file=org.apache.dubbo.rpc.cluster.router.file.FileRouterFactory
 script=org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory
-condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
\ No newline at end of file
+condition=org.apache.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
+tag=org.apache.dubbo.rpc.cluster.router.tag.TagRouterFactory
\ No newline at end of file
diff --git 
a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java
 
b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java
new file mode 100644
index 0000000000..839af44efe
--- /dev/null
+++ 
b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.tag;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.cluster.Router;
+import org.apache.dubbo.rpc.cluster.RouterFactory;
+import org.apache.dubbo.rpc.cluster.router.MockInvoker;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TagRouterTest {
+
+    private URL tagUrl = new URL("tag"
+            , Constants.ANYHOST_VALUE, 0
+            , Constants.ANY_VALUE)
+            .addParameters(
+                    Constants.RUNTIME_KEY, "true"
+            );
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+    }
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @Test
+    public void testRoute_matchTag() {
+
+        RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY, 
"red");
+
+        List<Invoker<String>> invokers = new ArrayList<>();
+        Invoker<String> redInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.1:20880/com.foo.BarService?tag=red"));
+        Invoker<String> yellowInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.2:20880/com.foo.BarService?tag=yellow"));
+        Invoker<String> blueInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.3:20880/com.foo.BarService?tag=blue"));
+        Invoker<String> defaultInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.4:20880/com.foo.BarService"));
+
+        invokers.add(redInvoker);
+        invokers.add(yellowInvoker);
+        invokers.add(blueInvoker);
+        invokers.add(defaultInvoker);
+
+        Router tagRouter = new TagRouterFactory().getRouter(tagUrl);
+        List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, 
URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), 
new RpcInvocation());
+        Assert.assertTrue(filteredInvokers.contains(redInvoker));
+        Assert.assertFalse(filteredInvokers.contains(yellowInvoker));
+        Assert.assertFalse(filteredInvokers.contains(blueInvoker));
+        Assert.assertFalse(filteredInvokers.contains(defaultInvoker));
+    }
+
+    @Test
+    public void testRoute_matchDefault() {
+
+        RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY, "");
+
+        List<Invoker<String>> invokers = new ArrayList<>();
+        Invoker<String> redInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.1:20880/com.foo.BarService?tag=red"));
+        Invoker<String> yellowInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.2:20880/com.foo.BarService?tag=yellow"));
+        Invoker<String> blueInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.3:20880/com.foo.BarService?tag=blue"));
+        Invoker<String> defaultInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.4:20880/com.foo.BarService"));
+
+        invokers.add(redInvoker);
+        invokers.add(yellowInvoker);
+        invokers.add(blueInvoker);
+        invokers.add(defaultInvoker);
+
+        Router tagRouter = new TagRouterFactory().getRouter(tagUrl);
+        List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, 
URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), 
new RpcInvocation());
+        Assert.assertTrue(filteredInvokers.contains(defaultInvoker));
+        Assert.assertFalse(filteredInvokers.contains(yellowInvoker));
+        Assert.assertFalse(filteredInvokers.contains(blueInvoker));
+        Assert.assertFalse(filteredInvokers.contains(redInvoker));
+    }
+
+    @Test
+    public void testRoute_requestWithTag_shouldDowngrade() {
+
+        RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY, 
"black");
+
+        List<Invoker<String>> invokers = new ArrayList<>();
+        Invoker<String> redInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.1:20880/com.foo.BarService?tag=red"));
+        Invoker<String> yellowInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.2:20880/com.foo.BarService?tag=yellow"));
+        Invoker<String> blueInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.3:20880/com.foo.BarService?tag=blue"));
+        Invoker<String> defaultInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.4:20880/com.foo.BarService"));
+
+        invokers.add(redInvoker);
+        invokers.add(yellowInvoker);
+        invokers.add(blueInvoker);
+        invokers.add(defaultInvoker);
+
+        Router tagRouter = new TagRouterFactory().getRouter(tagUrl);
+        List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, 
URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), 
new RpcInvocation());
+        Assert.assertTrue(filteredInvokers.contains(defaultInvoker));
+        Assert.assertFalse(filteredInvokers.contains(yellowInvoker));
+        Assert.assertFalse(filteredInvokers.contains(blueInvoker));
+        Assert.assertFalse(filteredInvokers.contains(redInvoker));
+    }
+
+    @Test
+    public void testRoute_requestWithoutTag_shouldNotDowngrade() {
+
+        RpcContext.getContext().setAttachment(Constants.REQUEST_TAG_KEY, "");
+
+        List<Invoker<String>> invokers = new ArrayList<>();
+        Invoker<String> redInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.1:20880/com.foo.BarService?tag=red"));
+        Invoker<String> yellowInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.2:20880/com.foo.BarService?tag=yellow"));
+        Invoker<String> blueInvoker = new MockInvoker<>(URL.valueOf(
+                "dubbo://10.20.3.3:20880/com.foo.BarService?tag=blue"));
+
+        invokers.add(redInvoker);
+        invokers.add(yellowInvoker);
+        invokers.add(blueInvoker);
+
+        Router tagRouter = new TagRouterFactory().getRouter(tagUrl);
+        List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, 
URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), 
new RpcInvocation());
+        Assert.assertEquals(0, filteredInvokers.size());
+    }
+
+    @Test
+    public void testRoute_createBySpi() {
+        URL zkProvider = 
URL.valueOf("zookeeper://10.20.3.1:20880/com.foo.BarService?router=tag");
+        String parameter = zkProvider.getParameter(Constants.ROUTER_KEY);
+        RouterFactory routerFactory = 
ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(parameter);
+        Router tagRouter = routerFactory.getRouter(zkProvider);
+        Assert.assertTrue(tagRouter instanceof TagRouter);
+    }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java 
b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index a1c8fac34c..9506930690 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@ -641,6 +641,10 @@
 
     public static final String MULTICAST = "multicast";
 
+    public static final String TAG_KEY = "tag";
+
+    public static final String REQUEST_TAG_KEY = "request.tag";
+
     /*
      * private Constants(){ }
      */
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 91a4a1641d..70ab62e449 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -522,5 +522,4 @@ public String getScope() {
     public void setScope(String scope) {
         this.scope = scope;
     }
-
 }
\ No newline at end of file
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
index 08f3ad5e97..552ccf1e4a 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
@@ -197,5 +197,4 @@ public void setGroup(String group) {
         checkKey("group", group);
         this.group = group;
     }
-
 }
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
index f23341fff1..4da1ffa89d 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
@@ -73,6 +73,9 @@
     // serialization
     private String serialization;
 
+    // provider tag
+    protected String tag;
+
     public String getVersion() {
         return version;
     }
@@ -240,4 +243,11 @@ public void setSerialization(String serialization) {
         this.serialization = serialization;
     }
 
+    public String getTag() {
+        return tag;
+    }
+
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
 }
diff --git 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
index bee838745e..6f956f50c0 100644
--- 
a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
+++ 
b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
@@ -263,4 +263,9 @@
      * Registry spring bean name
      */
     String[] registry() default {};
+
+    /**
+     * Service tag name
+     */
+    String tag() default "";
 }
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java
 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java
index 61513547c1..7612c3302a 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java
+++ 
b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java
@@ -33,7 +33,6 @@
 import org.apache.dubbo.config.ServiceConfig;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.annotation.Service;
-
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -76,7 +75,7 @@ public String getPackage() {
     public void setPackage(String annotationPackage) {
         this.annotationPackage = annotationPackage;
         this.annotationPackages = (annotationPackage == null || 
annotationPackage.length() == 0) ? null
-            : Constants.COMMA_SPLIT_PATTERN.split(annotationPackage);
+                : Constants.COMMA_SPLIT_PATTERN.split(annotationPackage);
     }
 
     @Override
@@ -86,7 +85,7 @@ public void setApplicationContext(ApplicationContext 
applicationContext) throws
 
     @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory 
beanFactory)
-        throws BeansException {
+            throws BeansException {
         if (annotationPackage == null || annotationPackage.length() == 0) {
             return;
         }
@@ -135,7 +134,7 @@ public void destroy() {
 
     @Override
     public Object postProcessAfterInitialization(Object bean, String beanName)
-        throws BeansException {
+            throws BeansException {
         if (!isMatchPackage(bean)) {
             return bean;
         }
@@ -144,7 +143,7 @@ public Object postProcessAfterInitialization(Object bean, 
String beanName)
             ServiceBean<Object> serviceConfig = new 
ServiceBean<Object>(service);
             serviceConfig.setRef(bean);
             if (void.class.equals(service.interfaceClass())
-                && "".equals(service.interfaceName())) {
+                    && "".equals(service.interfaceName())) {
                 if (bean.getClass().getInterfaces().length > 0) {
                     
serviceConfig.setInterface(bean.getClass().getInterfaces()[0]);
                 } else {
@@ -186,6 +185,9 @@ public Object postProcessAfterInitialization(Object bean, 
String beanName)
                     }
                     serviceConfig.setProtocols(protocolConfigs);
                 }
+                if (service.tag().length() > 0) {
+                    serviceConfig.setTag(service.tag());
+                }
                 try {
                     serviceConfig.afterPropertiesSet();
                 } catch (RuntimeException e) {
@@ -202,7 +204,7 @@ public Object postProcessAfterInitialization(Object bean, 
String beanName)
 
     @Override
     public Object postProcessBeforeInitialization(Object bean, String beanName)
-        throws BeansException {
+            throws BeansException {
         if (!isMatchPackage(bean)) {
             return bean;
         }
@@ -210,9 +212,9 @@ public Object postProcessBeforeInitialization(Object bean, 
String beanName)
         for (Method method : methods) {
             String name = method.getName();
             if (name.length() > 3 && name.startsWith("set")
-                && method.getParameterTypes().length == 1
-                && Modifier.isPublic(method.getModifiers())
-                && !Modifier.isStatic(method.getModifiers())) {
+                    && method.getParameterTypes().length == 1
+                    && Modifier.isPublic(method.getModifiers())
+                    && !Modifier.isStatic(method.getModifiers())) {
                 try {
                     Reference reference = 
method.getAnnotation(Reference.class);
                     if (reference != null) {
@@ -262,8 +264,8 @@ private Object refer(Reference reference, Class<?> 
referenceClass) { //method.ge
         if (referenceConfig == null) {
             referenceConfig = new ReferenceBean<Object>(reference);
             if (void.class.equals(reference.interfaceClass())
-                && "".equals(reference.interfaceName())
-                && referenceClass.isInterface()) {
+                    && "".equals(reference.interfaceName())
+                    && referenceClass.isInterface()) {
                 referenceConfig.setInterface(referenceClass);
             }
             if (applicationContext != null) {
diff --git 
a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd 
b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index 6206048311..290c750c93 100644
--- 
a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ 
b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -307,6 +307,12 @@
                         <xsd:documentation><![CDATA[ The serialization 
protocol of service. ]]></xsd:documentation>
                     </xsd:annotation>
                 </xsd:attribute>
+                <xsd:attribute name="tag" type="xsd:string">
+                    <xsd:annotation>
+                        <xsd:documentation>
+                            <![CDATA[ Defines the service 
tag]]></xsd:documentation>
+                    </xsd:annotation>
+                </xsd:attribute>
                 <xsd:anyAttribute namespace="##other" processContents="lax"/>
             </xsd:extension>
         </xsd:complexContent>
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 ecf7d7b7a5..ecec23acc0 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
@@ -307,6 +307,12 @@
                         <xsd:documentation><![CDATA[ The serialization 
protocol of service. ]]></xsd:documentation>
                     </xsd:annotation>
                 </xsd:attribute>
+                <xsd:attribute name="tag" type="xsd:string">
+                    <xsd:annotation>
+                        <xsd:documentation>
+                            <![CDATA[ Defines the service 
tag]]></xsd:documentation>
+                    </xsd:annotation>
+                </xsd:attribute>
                 <xsd:anyAttribute namespace="##other" processContents="lax"/>
             </xsd:extension>
         </xsd:complexContent>
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 727bca297e..6b366b2921 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
@@ -55,7 +55,6 @@
 
 /**
  * RegistryDirectory
- *
  */
 public class RegistryDirectory<T> extends AbstractDirectory<T> implements 
NotifyListener {
 
@@ -445,7 +444,8 @@ private URL mergeUrl(URL providerUrl) {
         List<Router> routers = getRouters();
         if (routers != null) {
             for (Router router : routers) {
-                if (router.getUrl() != null) {
+                // If router's url not null and is not route by runtime,we 
filter invokers here
+                if (router.getUrl() != null && 
!router.getUrl().getParameter(Constants.RUNTIME_KEY, false)) {
                     invokers = router.route(invokers, getConsumerUrl(), 
invocation);
                 }
             }
@@ -573,8 +573,8 @@ private void destroyUnusedInvokers(Map<String, Invoker<T>> 
oldUrlInvokerMap, Map
         if (forbidden) {
             // 1. No service provider 2. Service providers are disabled
             throw new RpcException(RpcException.FORBIDDEN_EXCEPTION,
-                "No provider available from registry " + getUrl().getAddress() 
+ " for service " + getConsumerUrl().getServiceKey() + " on consumer " +  
NetUtils.getLocalHost()
-                        + " use dubbo version " + Version.getVersion() + ", 
please check status of providers(disabled, not registered or in blacklist).");
+                    "No provider available from registry " + 
getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " 
on consumer " + NetUtils.getLocalHost()
+                            + " use dubbo version " + Version.getVersion() + 
", please check status of providers(disabled, not registered or in 
blacklist).");
         }
         List<Invoker<T>> invokers = null;
         Map<String, List<Invoker<T>>> localMethodInvokerMap = 
this.methodInvokerMap; // local reference


 

----------------------------------------------------------------
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:
[email protected]


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to