@@ -88,7 +88,7 @@ public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation
8888 }
8989
9090 if (tagRouterRule == null || !tagRouterRule .isValid () || !tagRouterRule .isEnabled ()) {
91- return invokers ;
91+ return filterUsingStaticTag ( invokers , url , invocation ) ;
9292 }
9393
9494 List <Invoker <T >> result = invokers ;
@@ -112,7 +112,7 @@ public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation
112112 }
113113 // If there's no tagged providers that can match the current tagged request. force.tag is set by default
114114 // to false, which means it will invoke any providers without a tag unless it's explicitly disallowed.
115- if (CollectionUtils .isNotEmpty (result ) || isForceUse (invocation )) {
115+ if (CollectionUtils .isNotEmpty (result ) || isForceUseTag (invocation )) {
116116 return result ;
117117 }
118118 // FAILOVER: return all Providers without any tags.
@@ -141,6 +141,37 @@ public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation
141141 }
142142 }
143143
144+ /**
145+ * If there's no dynamic tag rule being set, use static tag in URL.
146+ *
147+ * A typical scenario is a Consumer using version 2.7.x calls Providers using version 2.6.x or lower,
148+ * the Consumer should always respect the tag in provider URL regardless of whether a dynamic tag rule has been set to it or not.
149+ *
150+ * TODO, to guarantee consistent behavior of interoperability between 2.6- and 2.7+, this method should has the same logic with the TagRouter in 2.6.x.
151+ *
152+ * @param invokers
153+ * @param url
154+ * @param invocation
155+ * @param <T>
156+ * @return
157+ */
158+ private <T > List <Invoker <T >> filterUsingStaticTag (List <Invoker <T >> invokers , URL url , Invocation invocation ) {
159+ List <Invoker <T >> result = invokers ;
160+ // Dynamic param
161+ String tag = StringUtils .isEmpty (invocation .getAttachment (TAG_KEY )) ? url .getParameter (TAG_KEY ) :
162+ invocation .getAttachment (TAG_KEY );
163+ // Tag request
164+ if (!StringUtils .isEmpty (tag )) {
165+ result = filterInvoker (invokers , invoker -> tag .equals (invoker .getUrl ().getParameter (Constants .TAG_KEY )));
166+ if (CollectionUtils .isEmpty (result ) && !isForceUseTag (invocation )) {
167+ result = filterInvoker (invokers , invoker -> StringUtils .isEmpty (invoker .getUrl ().getParameter (Constants .TAG_KEY )));
168+ }
169+ } else {
170+ result = filterInvoker (invokers , invoker -> StringUtils .isEmpty (invoker .getUrl ().getParameter (Constants .TAG_KEY )));
171+ }
172+ return result ;
173+ }
174+
144175 @ Override
145176 public int getPriority () {
146177 return DEFAULT_PRIORITY ;
@@ -157,7 +188,7 @@ public boolean isForce() {
157188 return tagRouterRule != null && tagRouterRule .isForce ();
158189 }
159190
160- private boolean isForceUse (Invocation invocation ) {
191+ private boolean isForceUseTag (Invocation invocation ) {
161192 return Boolean .valueOf (invocation .getAttachment (FORCE_USE_TAG , url .getParameter (FORCE_USE_TAG , "false" )));
162193 }
163194
0 commit comments