From 4a124c6559191927aae96e3d5fc5f5c87cb269e0 Mon Sep 17 00:00:00 2001 From: tingfeng Date: Tue, 22 Aug 2023 16:34:18 +0800 Subject: [PATCH 1/3] merge 3.3 to 3.2-tag-level --- .../dubbo/common/utils/StringUtils.java | 18 +++++++ .../dubbo/common/utils/StringUtilsTest.java | 6 ++- .../cluster/router/tag/TagStateRouter.java | 36 +++++++++++++- .../router/tag/TagStateRouterTest.java | 48 ++++++++++++++++++- 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java index 31372ca8a37..45e63c1ce50 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.utils; +import java.util.StringJoiner; import org.apache.dubbo.common.io.UnsafeStringWriter; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -856,6 +857,23 @@ public static String join(Collection coll, String split) { return sb.toString(); } + public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) { + if (ArrayUtils.isEmpty(array)) { + return EMPTY_STRING; + } + if (endIndex - startIndex <= 0) { + return EMPTY_STRING; + } + StringBuilder sb = new StringBuilder(); + for (int i = startIndex; i < endIndex; i++) { + if (i > 0) { + sb.append(delimiter); + } + sb.append(array[i]); + } + return sb.toString(); + } + /** * parse key-value pair. * diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java index 5d46c2ad18b..2ac7ccc411c 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java @@ -227,6 +227,10 @@ void testJoin() throws Exception { assertEquals(StringUtils.join(s), "123"); assertEquals(StringUtils.join(s, ','), "1,2,3"); assertEquals(StringUtils.join(s, ","), "1,2,3"); + assertEquals(StringUtils.join(s, ',', 0, 1), "1"); + assertEquals(StringUtils.join(s, ',', 0, 2), "1,2"); + assertEquals(StringUtils.join(s, ',', 0, 3), "1,2,3"); + assertEquals("", StringUtils.join(s, ',', 2, 0), "1,2"); } @Test @@ -502,4 +506,4 @@ void testStartsWithIgnoreCase() { assertTrue(startsWithIgnoreCase("Dubbo.application.name", "dubbo.application.")); } -} \ No newline at end of file +} diff --git a/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java b/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java index c3470776b25..28bfa71544d 100644 --- a/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java +++ b/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java @@ -36,6 +36,7 @@ import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule; import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser; +import java.util.Map; import java.util.Set; import java.util.function.Predicate; @@ -52,6 +53,7 @@ public class TagStateRouter extends AbstractStateRouter implements Configu public static final String NAME = "TAG_ROUTER"; private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(TagStateRouter.class); private static final String RULE_SUFFIX = ".tag-router"; + public static final char TAG_SEPERATOR = '|'; private volatile TagRouterRule tagRouterRule; private String application; @@ -106,7 +108,8 @@ public BitList> doRoute(BitList> invokers, URL url, Invoca // if we are requesting for a Provider with a specific tag if (StringUtils.isNotEmpty(tag)) { - Set addresses = tagRouterRuleCopy.getTagnameToAddresses().get(tag); + Map> tagnameToAddresses = tagRouterRuleCopy.getTagnameToAddresses(); + Set addresses = selectAddressByTagLevel(tagnameToAddresses, tag, isForceUseTag(invocation)); // filter by dynamic tag group first if (addresses != null) { // null means tag not set result = filterInvoker(invokers, invoker -> addressMatches(invoker.getUrl(), addresses)); @@ -306,4 +309,35 @@ public void stop() { public void setTagRouterRule(TagRouterRule tagRouterRule) { this.tagRouterRule = tagRouterRule; } + + /** + * select addresses by tag with level + *

+ * example: + * selector=beta|team1|partner1 + * step1.select tagAddresses with selector=beta|team1|partner1, if result is empty, then run step2 + * step2.select tagAddresses with selector=beta|team1, if result is empty, then run step3 + * step3.select tagAddresses with selector=beta, if result is empty, result is null + *

+ * + * @param tagAddresses + * @param tagSelector eg: beta|team1|partner1 + * @return + */ + public static Set selectAddressByTagLevel(Map> tagAddresses, String tagSelector, boolean isForce) { + if (isForce || StringUtils.isNotContains(tagSelector, TAG_SEPERATOR)) { + return tagAddresses.get(tagSelector); + } + String[] selectors = StringUtils.split(tagSelector, TAG_SEPERATOR); + for (int i = selectors.length; i > 0; i--) { + String selectorTmp = StringUtils.join(selectors, TAG_SEPERATOR, 0, i); + System.out.println(selectorTmp); + Set addresses = tagAddresses.get(selectorTmp); + if (CollectionUtils.isNotEmpty(addresses)) { + return addresses; + } + } + return null; + } + } diff --git a/dubbo-plugin/dubbo-plugin-router-tag/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouterTest.java b/dubbo-plugin/dubbo-plugin-router-tag/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouterTest.java index 228a667eef8..6477c09b6c3 100644 --- a/dubbo-plugin/dubbo-plugin-router-tag/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouterTest.java +++ b/dubbo-plugin/dubbo-plugin-router-tag/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouterTest.java @@ -24,7 +24,6 @@ import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.cluster.router.MockInvoker; -//import org.apache.dubbo.rpc.cluster.router.mesh.util.TracingContextProvider; import org.apache.dubbo.rpc.cluster.router.state.BitList; import org.apache.dubbo.rpc.cluster.router.state.StateRouter; import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule; @@ -32,13 +31,17 @@ import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; +import com.google.common.collect.Sets; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; import static org.mockito.Mockito.when; @@ -256,4 +259,47 @@ private TagRouterRule getTagRule() { TagRouterRule tagRouterRule = TagRuleParser.parse(tagRouterRuleConfig); return tagRouterRule; } + + @Test + public void tagMultiLevelTest() { + String tagSelector = "beta|team1|partner1"; + Set address1 = Sets.newHashSet("192.168.5.1:20880"); + Map> tagAddresses = new HashMap<>(); + tagAddresses.put("beta", address1); + Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + + Set address2 = Sets.newHashSet("192.168.5.2:20880"); + tagAddresses.put("beta|team1", address2); + Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + + Set address3 = Sets.newHashSet("192.168.5.3:20880"); + tagAddresses.put("beta|team1|partner1", address3); + Assertions.assertEquals(address3, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + + tagSelector = "beta"; + Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + tagSelector = "beta|team1"; + Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + tagSelector = "beta|team1|partner1"; + Assertions.assertEquals(address3, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + + tagSelector = "beta2"; + Assertions.assertNull(TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + tagSelector = "beta|team2"; + Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + tagSelector = "beta|team1|partner2"; + Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false)); + + + } + + @Test + public void tagLevelForceTest() { + Set addresses = Sets.newHashSet("192.168.1.223:20880"); + Map> tagAddresses = new HashMap<>(); + tagAddresses.put("beta", addresses); + Set selectedAddresses = TagStateRouter.selectAddressByTagLevel(tagAddresses, "beta", true); + Assertions.assertEquals(addresses, selectedAddresses); + } + } From b351b3920ecdf7dda65810bfdfeac33c65d2cd8f Mon Sep 17 00:00:00 2001 From: tingfeng Date: Wed, 5 Jul 2023 15:28:00 +0800 Subject: [PATCH 2/3] remove redundant import --- .../src/main/java/org/apache/dubbo/common/utils/StringUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java index 45e63c1ce50..34fa8b5403b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java @@ -16,7 +16,6 @@ */ package org.apache.dubbo.common.utils; -import java.util.StringJoiner; import org.apache.dubbo.common.io.UnsafeStringWriter; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; From 6d4d349e46075e6d4ec5c4bbe93f8b83c2f14246 Mon Sep 17 00:00:00 2001 From: carlvine500 Date: Tue, 22 Aug 2023 10:29:04 +0800 Subject: [PATCH 3/3] remove System.out.println --- .../org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java b/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java index 28bfa71544d..f6e7d9dc334 100644 --- a/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java +++ b/dubbo-plugin/dubbo-plugin-router-tag/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStateRouter.java @@ -331,7 +331,6 @@ public static Set selectAddressByTagLevel(Map> tagAd String[] selectors = StringUtils.split(tagSelector, TAG_SEPERATOR); for (int i = selectors.length; i > 0; i--) { String selectorTmp = StringUtils.join(selectors, TAG_SEPERATOR, 0, i); - System.out.println(selectorTmp); Set addresses = tagAddresses.get(selectorTmp); if (CollectionUtils.isNotEmpty(addresses)) { return addresses;