tag support multi level (#12673)
This commit is contained in:
parent
4e9a0a41fc
commit
679ce4496c
|
|
@ -856,6 +856,23 @@ public final class StringUtils {
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -227,6 +227,10 @@ class StringUtilsTest {
|
|||
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 @@ class StringUtilsTest {
|
|||
assertTrue(startsWithIgnoreCase("Dubbo.application.name", "dubbo.application."));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
|||
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<T> extends AbstractStateRouter<T> 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 class TagStateRouter<T> extends AbstractStateRouter<T> implements Configu
|
|||
|
||||
// if we are requesting for a Provider with a specific tag
|
||||
if (StringUtils.isNotEmpty(tag)) {
|
||||
Set<String> addresses = tagRouterRuleCopy.getTagnameToAddresses().get(tag);
|
||||
Map<String, Set<String>> tagnameToAddresses = tagRouterRuleCopy.getTagnameToAddresses();
|
||||
Set<String> 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,34 @@ public class TagStateRouter<T> extends AbstractStateRouter<T> implements Configu
|
|||
public void setTagRouterRule(TagRouterRule tagRouterRule) {
|
||||
this.tagRouterRule = tagRouterRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* select addresses by tag with level
|
||||
* <p>
|
||||
* 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
|
||||
* </p>
|
||||
*
|
||||
* @param tagAddresses
|
||||
* @param tagSelector eg: beta|team1|partner1
|
||||
* @return
|
||||
*/
|
||||
public static Set<String> selectAddressByTagLevel(Map<String, Set<String>> 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);
|
||||
Set<String> addresses = tagAddresses.get(selectorTmp);
|
||||
if (CollectionUtils.isNotEmpty(addresses)) {
|
||||
return addresses;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import org.apache.dubbo.common.utils.Holder;
|
|||
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.cluster.router.tag.model.TagRuleParser;
|
|||
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 @@ class TagStateRouterTest {
|
|||
TagRouterRule tagRouterRule = TagRuleParser.parse(tagRouterRuleConfig);
|
||||
return tagRouterRule;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tagMultiLevelTest() {
|
||||
String tagSelector = "beta|team1|partner1";
|
||||
Set<String> address1 = Sets.newHashSet("192.168.5.1:20880");
|
||||
Map<String, Set<String>> tagAddresses = new HashMap<>();
|
||||
tagAddresses.put("beta", address1);
|
||||
Assertions.assertEquals(address1, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||
|
||||
Set<String> address2 = Sets.newHashSet("192.168.5.2:20880");
|
||||
tagAddresses.put("beta|team1", address2);
|
||||
Assertions.assertEquals(address2, TagStateRouter.selectAddressByTagLevel(tagAddresses, tagSelector, false));
|
||||
|
||||
Set<String> 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<String> addresses = Sets.newHashSet("192.168.1.223:20880");
|
||||
Map<String, Set<String>> tagAddresses = new HashMap<>();
|
||||
tagAddresses.put("beta", addresses);
|
||||
Set<String> selectedAddresses = TagStateRouter.selectAddressByTagLevel(tagAddresses, "beta", true);
|
||||
Assertions.assertEquals(addresses, selectedAddresses);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue