From f1e8a84ecaa55ab96394286457ff0b3cae7a4bd3 Mon Sep 17 00:00:00 2001 From: chengyouling Date: Mon, 18 Dec 2023 11:00:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A0=87=E7=AD=BE=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E5=8C=B9=E9=85=8Dfallback=E8=A7=84=E5=88=99=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/AbstractDirectoryServiceImpl.java | 6 +- .../dubbo/strategy/RuleStrategyHandler.java | 7 +- .../router/dubbo/utils/RouteUtils.java | 8 +- .../strategy/RuleStrategyHandlerTest.java | 121 +++++++++++++++++- .../sermant/router/config/entity/Rule.java | 13 ++ .../config/strategy/AbstractRuleStrategy.java | 28 +++- .../router/config/strategy/RuleStrategy.java | 5 +- .../service/LoadBalancerServiceImpl.java | 8 +- .../spring/strategy/RuleStrategyHandler.java | 7 +- .../router/spring/utils/RouteUtils.java | 7 +- .../strategy/RuleStrategyHandlerTest.java | 115 ++++++++++++++++- 11 files changed, 294 insertions(+), 31 deletions(-) diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java index 649a80b301..102c5fbf70 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java @@ -195,10 +195,10 @@ private List getTargetInvokersByRules(List invokers, Object invo + DubboReflectUtils.getMethodName(invocation) + ":" + getVersion(queryMap); List rules = RuleUtils .getRules(configuration, targetService, interfaceName, DubboCache.INSTANCE.getAppName()); - List routes = RouteUtils.getRoutes(rules, DubboReflectUtils.getArguments(invocation), + Optional matchRuleOptional = RouteUtils.getRule(rules, DubboReflectUtils.getArguments(invocation), parseAttachments(invocation)); - if (!CollectionUtils.isEmpty(routes)) { - return RuleStrategyHandler.INSTANCE.getMatchInvokers(targetService, invokers, routes); + if (matchRuleOptional.isPresent()) { + return RuleStrategyHandler.INSTANCE.getMatchInvokers(targetService, invokers, matchRuleOptional.get()); } return RuleStrategyHandler.INSTANCE .getMismatchInvokers(targetService, invokers, RuleUtils.getTags(rules, true), true); diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java index c03bbc00a1..4d47cfba67 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java @@ -17,6 +17,7 @@ package com.huaweicloud.sermant.router.dubbo.strategy; import com.huaweicloud.sermant.router.config.entity.Route; +import com.huaweicloud.sermant.router.config.entity.Rule; import com.huaweicloud.sermant.router.config.strategy.RuleStrategy; import com.huaweicloud.sermant.router.dubbo.strategy.rule.InvokerRuleStrategy; @@ -46,11 +47,11 @@ public enum RuleStrategyHandler { * * @param serviceName 服务名 * @param invokers dubbo invokers - * @param routes 路由规则 + * @param rule 路由规则 * @return 标签应用的invokers */ - public List getMatchInvokers(String serviceName, List invokers, List routes) { - return ruleStrategy.getMatchInstances(serviceName, invokers, routes, true); + public List getMatchInvokers(String serviceName, List invokers, Rule rule) { + return ruleStrategy.getMatchInstances(serviceName, invokers, rule, true); } /** diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/RouteUtils.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/RouteUtils.java index 305eb0327b..cc3f390c7d 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/RouteUtils.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/utils/RouteUtils.java @@ -50,11 +50,11 @@ private RouteUtils() { * @param attachments dubbo的attachments参数 * @return 匹配的路由 */ - public static List getRoutes(List list, Object[] arguments, Map attachments) { + public static Optional getRule(List list, Object[] arguments, Map attachments) { for (Rule rule : list) { Match match = rule.getMatch(); if (match == null) { - return rule.getRoute(); + return Optional.of(rule); } List routeList; if (!CollectionUtils.isEmpty(match.getAttachments()) && !CollectionUtils.isEmpty(attachments)) { @@ -65,10 +65,10 @@ public static List getRoutes(List list, Object[] arguments, Map routes; + private final Rule rule; + /** * 构造方法 */ public RuleStrategyHandlerTest() { + rule = new Rule(); routes = new ArrayList<>(); Map tags1 = new HashMap<>(); tags1.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.1"); @@ -56,6 +60,7 @@ public RuleStrategyHandlerTest() { route2.setTags(tags2); route2.setWeight(100); routes.add(route2); + rule.setRoute(routes); } /** @@ -68,7 +73,7 @@ public void testAlibabaV1() { invokers.add(invoker1); AlibabaInvoker invoker2 = new AlibabaInvoker<>("0.0.2"); invokers.add(invoker2); - List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, routes); + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); Assert.assertEquals(100, routes.get(0).getWeight().intValue()); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker1, matchInvokers.get(0)); @@ -103,7 +108,7 @@ public void testAlibabaMismatch() { routes.get(0).setWeight(0); // 测试匹配上路由,没有随机到实例的情况 - List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, routes); + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker2, matchInvokers.get(0)); @@ -147,7 +152,7 @@ public void testApacheV1() { invokers.add(invoker1); ApacheInvoker invoker2 = new ApacheInvoker<>("0.0.2"); invokers.add(invoker2); - List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, routes); + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); Assert.assertEquals(100, routes.get(0).getWeight().intValue()); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker1, matchInvokers.get(0)); @@ -183,7 +188,7 @@ public void testApacheMismatch() { routes.get(0).setWeight(0); // 测试匹配上路由,没有随机到实例的情况 - List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, routes); + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker2, matchInvokers.get(0)); @@ -216,4 +221,112 @@ public void testApacheZone() { Assert.assertEquals(2, mismatchInvoker.size()); Assert.assertEquals(invokers, mismatchInvoker); } + + /** + * 测试alibaba rule中route有选中tag,但是没有符合版本的实例,invoker命中fallback版本实例的情况 + */ + @Test + public void testAlibabaV1Fallback() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + + List invokers = new ArrayList<>(); + AlibabaInvoker invoker1 = new AlibabaInvoker<>("0.0.3"); + invokers.add(invoker1); + AlibabaInvoker invoker2 = new AlibabaInvoker<>("0.0.4"); + invokers.add(invoker2); + + // Route随机命中route1,但是没有0.0.1版本实例;命中fallback,返回fallback实例信息 + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); + Assert.assertEquals(100, routes.get(0).getWeight().intValue()); + Assert.assertEquals(1, matchInvokers.size()); + Assert.assertEquals(invoker1, matchInvokers.get(0)); + } + + /** + * 测试alibaba rule中设置route、fallback,且权重均有命中tag,但是invoker均未命中版本实例的情况 + */ + @Test + public void testAlibabaV1NotMathRouteFallback() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + + List invokers = new ArrayList<>(); + ApacheInvoker invoker1 = new ApacheInvoker<>("0.0.2"); + invokers.add(invoker1); + ApacheInvoker invoker2 = new ApacheInvoker<>("0.0.4"); + invokers.add(invoker2); + + // Route随机命中route1,但是没有0.0.1版本实例,fallback也未命中tag实例,所以返回全部实例信息 + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); + Assert.assertEquals(2, matchInvokers.size()); + } + + /** + * 测试alibaba rule中设置routes但权重计算未命中,invoker命中fallback版本实例的情况 + */ + @Test + public void testAlibabaV1MathFallback() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + routes.get(0).setWeight(0); + routes.get(1).setWeight(0); + + List invokers = new ArrayList<>(); + ApacheInvoker invoker1 = new ApacheInvoker<>("0.0.2"); + invokers.add(invoker1); + ApacheInvoker invoker2 = new ApacheInvoker<>("0.0.3"); + invokers.add(invoker2); + + // Route计算权重均未命中tag,fallback权重计算命中tag,返回fallback规则命中实例信息 + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); + Assert.assertEquals(1, matchInvokers.size()); + Assert.assertEquals(invoker2, matchInvokers.get(0)); + } + + /** + * 测试alibaba rule中设置routes但权重计算未命中,同时fallback也未命中实例,invoker返回未设置规则版本号版本实例的情况 + */ + @Test + public void testAlibabaV1BothNotMathFallbackRoute() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + routes.get(0).setWeight(0); + routes.get(1).setWeight(0); + + List invokers = new ArrayList<>(); + ApacheInvoker invoker1 = new ApacheInvoker<>("0.0.1"); + invokers.add(invoker1); + ApacheInvoker invoker2 = new ApacheInvoker<>("0.0.4"); + invokers.add(invoker2); + + // Route计算权重均未命中tag,fallback权重计算也未命中tag,返回route中未设置tag实例信息 + List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, rule); + Assert.assertEquals(1, matchInvokers.size()); + Assert.assertEquals(invoker2, matchInvokers.get(0)); + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/Rule.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/Rule.java index 3ae4373e5a..bd42e4f0b4 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/Rule.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/Rule.java @@ -40,6 +40,11 @@ public class Rule { */ private List route; + /** + * 降级路由 + */ + private List fallback; + public void setPrecedence(int precedence) { this.precedence = precedence; } @@ -63,4 +68,12 @@ public void setRoute(List route) { public List getRoute() { return this.route; } + + public List getFallback() { + return fallback; + } + + public void setFallback(List fallback) { + this.fallback = fallback; + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java index d38d0803d1..654ea735f9 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/AbstractRuleStrategy.java @@ -19,7 +19,7 @@ import com.huaweicloud.sermant.core.common.LoggerFactory; import com.huaweicloud.sermant.core.utils.StringUtils; import com.huaweicloud.sermant.router.common.utils.CollectionUtils; -import com.huaweicloud.sermant.router.config.entity.Route; +import com.huaweicloud.sermant.router.config.entity.Rule; import com.huaweicloud.sermant.router.config.utils.RuleUtils; import com.huaweicloud.sermant.router.config.utils.RuleUtils.RouteResult; @@ -74,8 +74,30 @@ public AbstractRuleStrategy(String source, InstanceStrategy getMatchInstances(String serviceName, List instances, List routes, boolean isReplaceDash) { - RouteResult result = RuleUtils.getTargetTags(routes, isReplaceDash); + public List getMatchInstances(String serviceName, List instances, Rule rule, boolean isReplaceDash) { + // match set routes + RouteResult result = RuleUtils.getTargetTags(rule.getRoute(), isReplaceDash); + if (result.isMatch() && !CollectionUtils.isEmpty(rule.getFallback())) { + // fallback有设置路由规则时,仅返回匹配的实例,如果存在直接返回 + List routeInstances = getInstances(getStrategy(result.isMatch()), result.getTags(), serviceName, + instances, false); + if (!CollectionUtils.isEmpty(routeInstances)) { + return routeInstances; + } + } + + // route设置的目标标签未匹配实例时,fallback有设置路由,通过fallback路由目标标签实例 + if (!CollectionUtils.isEmpty(rule.getFallback())) { + RouteResult fallback = RuleUtils.getTargetTags(rule.getFallback(), isReplaceDash); + List fallbackInstances = getInstances(getStrategy(fallback.isMatch()), fallback.getTags(), serviceName, + instances, false); + + // fallback中设置了路由规则命中routeTag,且有对应的实例匹配则按fallback路由规则选中实例,返回对应实例 + if (!CollectionUtils.isEmpty(fallbackInstances)) { + return fallbackInstances; + } + } + return getInstances(getStrategy(result.isMatch()), result.getTags(), serviceName, instances, true); } diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java index 796df0f854..8d0cc27659 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/strategy/RuleStrategy.java @@ -17,6 +17,7 @@ package com.huaweicloud.sermant.router.config.strategy; import com.huaweicloud.sermant.router.config.entity.Route; +import com.huaweicloud.sermant.router.config.entity.Rule; import java.util.List; import java.util.Map; @@ -34,11 +35,11 @@ public interface RuleStrategy { * * @param serviceName 服务名 * @param instances 实例列表 - * @param routes 路由规则 + * @param rule 路由规则 * @param isReplaceDash 是否需要替换破折号为点号(dubbo需要) * @return 路由过滤后的实例 */ - List getMatchInstances(String serviceName, List instances, List routes, boolean isReplaceDash); + List getMatchInstances(String serviceName, List instances, Rule rule, boolean isReplaceDash); /** * 根据请求信息选取路由的实例 diff --git a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java index 18a38a1b88..0d5f48fafc 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceImpl.java @@ -23,7 +23,6 @@ import com.huaweicloud.sermant.router.common.utils.CollectionUtils; import com.huaweicloud.sermant.router.config.cache.ConfigCache; import com.huaweicloud.sermant.router.config.entity.EnabledStrategy; -import com.huaweicloud.sermant.router.config.entity.Route; import com.huaweicloud.sermant.router.config.entity.RouterConfiguration; import com.huaweicloud.sermant.router.config.entity.Rule; import com.huaweicloud.sermant.router.config.utils.RuleUtils; @@ -35,6 +34,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; /** * BaseLoadBalancerInterceptor服务 @@ -96,9 +96,9 @@ private List getTargetInstancesByRules(String targetName, List i return instances; } List rules = RuleUtils.getRules(configuration, targetName, path, AppCache.INSTANCE.getAppName()); - List routes = RouteUtils.getRoutes(rules, header); - if (!CollectionUtils.isEmpty(routes)) { - return RuleStrategyHandler.INSTANCE.getMatchInstances(targetName, instances, routes); + Optional ruleOptional = RouteUtils.getRoutes(rules, header); + if (ruleOptional.isPresent()) { + return RuleStrategyHandler.INSTANCE.getMatchInstances(targetName, instances, ruleOptional.get()); } return RuleStrategyHandler.INSTANCE .getMismatchInstances(targetName, instances, RuleUtils.getTags(rules, false), true); diff --git a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java index 4a46809ddc..6544c8ae7d 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandler.java @@ -17,6 +17,7 @@ package com.huaweicloud.sermant.router.spring.strategy; import com.huaweicloud.sermant.router.config.entity.Route; +import com.huaweicloud.sermant.router.config.entity.Rule; import com.huaweicloud.sermant.router.config.strategy.AbstractRuleStrategy; import com.huaweicloud.sermant.router.spring.strategy.mapper.AbstractMetadataMapper; import com.huaweicloud.sermant.router.spring.strategy.mapper.DefaultMetadataMapper; @@ -64,11 +65,11 @@ private void init(AbstractMetadataMapper mapper) { * * @param serviceName 服务名 * @param instances 实例列表 - * @param routes 路由规则 + * @param rule 路由规则 * @return 路由匹配的实例 */ - public List getMatchInstances(String serviceName, List instances, List routes) { - return getRuleStrategy(instances).getMatchInstances(serviceName, instances, routes, false); + public List getMatchInstances(String serviceName, List instances, Rule rule) { + return getRuleStrategy(instances).getMatchInstances(serviceName, instances, rule, false); } /** diff --git a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/utils/RouteUtils.java b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/utils/RouteUtils.java index 01985d0d54..157ae314e1 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/utils/RouteUtils.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/utils/RouteUtils.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; /** * 路由插件工具类 @@ -46,14 +47,14 @@ private RouteUtils() { * @param header header * @return 匹配的路由 */ - public static List getRoutes(List list, Map> header) { + public static Optional getRoutes(List list, Map> header) { for (Rule rule : list) { List routeList = getRoutes(header, rule); if (!CollectionUtils.isEmpty(routeList)) { - return routeList; + return Optional.of(rule); } } - return Collections.emptyList(); + return Optional.empty(); } private static List getRoutes(Map> header, Rule rule) { diff --git a/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java index 745b6f6505..c6fcad49d8 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java @@ -16,7 +16,9 @@ package com.huaweicloud.sermant.router.spring.strategy; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; import com.huaweicloud.sermant.router.config.entity.Route; +import com.huaweicloud.sermant.router.config.entity.Rule; import com.huaweicloud.sermant.router.spring.TestDefaultServiceInstance; import org.junit.Assert; @@ -38,10 +40,13 @@ public class RuleStrategyHandlerTest { private final List routes; + private final Rule rule; + /** * 构造方法 */ public RuleStrategyHandlerTest() { + rule = new Rule(); routes = new ArrayList<>(); Map tags1 = new HashMap<>(); tags1.put("version", "0.0.1"); @@ -55,6 +60,7 @@ public RuleStrategyHandlerTest() { route2.setTags(tags2); route2.setWeight(100); routes.add(route2); + rule.setRoute(routes); } /** @@ -67,7 +73,7 @@ public void testMatchV1() { instances.add(instance1); ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.2"); instances.add(instance2); - List matchInvoker = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, routes); + List matchInvoker = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, rule); Assert.assertEquals(100, routes.get(0).getWeight().intValue()); Assert.assertEquals(1, matchInvoker.size()); Assert.assertEquals(instance1, matchInvoker.get(0)); @@ -102,7 +108,7 @@ public void testMismatchV1() { routes.get(0).setWeight(0); // 测试匹配上路由,没有随机到实例的情况 - List matchInstances = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, routes); + List matchInstances = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, rule); Assert.assertEquals(1, matchInstances.size()); Assert.assertEquals(instance2, matchInstances.get(0)); @@ -136,4 +142,109 @@ public void testZoneFoo() { Assert.assertEquals(2, mismatchInstances.size()); Assert.assertEquals(instances, mismatchInstances); } + + /** + * rule中route有命中tag,但是没有符合版本的实例,invoker命中fallback版本实例的情况 + */ + @Test + public void testMatchV1Fallback() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.3"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.4"); + instances.add(instance2); + + // Route随机命中route1,但是没有0.0.1版本实例;命中fallback,返回fallback实例信息 + List matchInvoker = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, rule); + Assert.assertEquals(100, routes.get(0).getWeight().intValue()); + Assert.assertEquals(1, matchInvoker.size()); + Assert.assertEquals(instance1, matchInvoker.get(0)); + } + + /** + * rule中设置route、fallback,且权重均有命中tag,但是invoker均未命中版本实例的情况 + */ + @Test + public void testSpringV1NotMathRouteFallback() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.2"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.4"); + instances.add(instance2); + // Route随机命中route1,但是没有0.0.1版本实例,fallback也未命中tag实例,所以返回全部实例信息 + List matchInvoker = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, rule); + Assert.assertEquals(2, matchInvoker.size()); + } + + /** + * rule中设置routes但权重计算未命中,invoker命中fallback版本实例的情况 + */ + @Test + public void testSpringV1MathFallback() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + routes.get(0).setWeight(0); + routes.get(1).setWeight(0); + + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.2"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.3"); + instances.add(instance2); + // Route计算权重均未命中tag,fallback权重计算命中tag,返回fallback规则命中实例信息 + List matchInvoker = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, rule); + Assert.assertEquals(1, matchInvoker.size()); + Assert.assertEquals(instance2, matchInvoker.get(0)); + } + + /** + * rule中设置routes但权重计算未命中,同时fallback也未命中实例,invoker返回未设置规则版本号版本实例的情况 + */ + @Test + public void testSpringV1BothNotMathFallbackRoute() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + routes.get(0).setWeight(0); + routes.get(1).setWeight(0); + + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.1"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.4"); + instances.add(instance2); + // Route计算权重均未命中tag,fallback权重计算也未命中tag,返回route中未设置tag实例信息 + List matchInvoker = RuleStrategyHandler.INSTANCE.getMatchInstances("foo", instances, rule); + Assert.assertEquals(1, matchInvoker.size()); + Assert.assertEquals(instance2, matchInvoker.get(0)); + } } \ No newline at end of file