From 6e284a18754cca630eab97a2139f1a6dc1a07f17 Mon Sep 17 00:00:00 2001 From: provenceee <83857838+provenceee@users.noreply.github.com> Date: Wed, 10 Jan 2024 14:38:49 +0800 Subject: [PATCH] =?UTF-8?q?*=E5=A2=9E=E5=8A=A0fallback=E8=B7=AF=E7=94=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: provenceee <83857838+provenceee@users.noreply.github.com> --- .../dubbo/handler/FlowRouteHandler.java | 14 +-- .../dubbo/strategy/RuleStrategyHandler.java | 7 +- .../strategy/RuleStrategyHandlerTest.java | 102 +++++++++++++++++- .../sermant/router/config/entity/Rule.java | 13 +++ .../config/strategy/AbstractRuleStrategy.java | 33 +++++- .../router/config/strategy/RuleStrategy.java | 5 +- .../router/config/utils/RuleUtils.java | 6 ++ .../spring/handler/FlowRouteHandler.java | 13 +-- .../spring/strategy/RuleStrategyHandler.java | 7 +- .../strategy/RuleStrategyHandlerTest.java | 98 ++++++++++++++++- 10 files changed, 264 insertions(+), 34 deletions(-) diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/handler/FlowRouteHandler.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/handler/FlowRouteHandler.java index 2f6fab00e1..9f83d69819 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/handler/FlowRouteHandler.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/handler/FlowRouteHandler.java @@ -105,10 +105,10 @@ private List getTargetInvokersByRules(List invokers, Object invo if (CollectionUtils.isEmpty(rules)) { return invokers; } - List routes = getRoutes(rules, DubboReflectUtils.getArguments(invocation), + Optional ruleOptional = getRule(rules, DubboReflectUtils.getArguments(invocation), parseAttachments(invocation)); - if (!CollectionUtils.isEmpty(routes)) { - return RuleStrategyHandler.INSTANCE.getMatchInvokers(targetService, invokers, routes); + if (ruleOptional.isPresent()) { + return RuleStrategyHandler.INSTANCE.getFlowMatchInvokers(targetService, invokers, ruleOptional.get()); } return RuleStrategyHandler.INSTANCE .getMismatchInvokers(targetService, invokers, RuleUtils.getTags(rules), true); @@ -202,11 +202,11 @@ private String getVersion(Map queryMap) { * @param attachments dubbo的attachments参数 * @return 匹配的路由 */ - private static List getRoutes(List list, Object[] arguments, Map attachments) { + private 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)) { @@ -217,10 +217,10 @@ private static List getRoutes(List list, Object[] arguments, Map getMatchInvokers(String serviceName, List invokers, List routes) { - return ruleStrategy.getMatchInstances(serviceName, invokers, routes); + public List getFlowMatchInvokers(String serviceName, List invokers, Rule rule) { + return ruleStrategy.getFlowMatchInstances(serviceName, invokers, rule); } /** diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java index 04f12cc9ee..ba832b511e 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java @@ -18,6 +18,7 @@ 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.dubbo.AlibabaInvoker; import com.huaweicloud.sermant.router.dubbo.ApacheInvoker; @@ -39,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(RouterConstant.META_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.getFlowMatchInvokers("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.getFlowMatchInvokers("foo", invokers, rule); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker2, matchInvokers.get(0)); @@ -125,7 +130,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.getFlowMatchInvokers("foo", invokers, rule); Assert.assertEquals(100, routes.get(0).getWeight().intValue()); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker1, matchInvokers.get(0)); @@ -162,7 +167,7 @@ public void testApacheMismatch() { routes.get(0).setWeight(0); // 测试匹配上路由,没有随机到实例的情况 - List matchInvokers = RuleStrategyHandler.INSTANCE.getMatchInvokers("foo", invokers, routes); + List matchInvokers = RuleStrategyHandler.INSTANCE.getFlowMatchInvokers("foo", invokers, rule); Assert.assertEquals(1, matchInvokers.size()); Assert.assertEquals(invoker2, matchInvokers.get(0)); @@ -173,4 +178,93 @@ public void testApacheMismatch() { Assert.assertEquals(1, mismatchInvoker.size()); Assert.assertEquals(invoker2, mismatchInvoker.get(0)); } + + /** + * rule中route有选中tag,但是没有符合版本的实例,invoker命中fallback版本实例的情况 + */ + @Test + public void testAlibabaV1Fallback() { + setFallbackRoute(); + 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.getFlowMatchInvokers("foo", invokers, rule); + Assert.assertEquals(100, routes.get(0).getWeight().intValue()); + Assert.assertEquals(1, matchInvokers.size()); + Assert.assertEquals(invoker1, matchInvokers.get(0)); + } + + private void setFallbackRoute() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.META_VERSION_KEY, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + } + + /** + * rule中设置route、fallback,且权重均有命中tag,但是invoker均未命中版本实例的情况 + */ + @Test + public void testAlibabaV1NotMathRouteFallback() { + setFallbackRoute(); + 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.getFlowMatchInvokers("foo", invokers, rule); + Assert.assertEquals(2, matchInvokers.size()); + } + + /** + * rule中设置routes但权重计算未命中,invoker命中fallback版本实例的情况 + */ + @Test + public void testAlibabaV1MathFallback() { + setFallbackRoute(); + 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.getFlowMatchInvokers("foo", invokers, rule); + Assert.assertEquals(1, matchInvokers.size()); + Assert.assertEquals(invoker2, matchInvokers.get(0)); + } + + /** + * rule中设置routes但权重计算未命中,同时fallback也未命中实例,invoker返回未设置规则版本号版本实例的情况 + */ + @Test + public void testAlibabaV1BothNotMathFallbackRoute() { + setFallbackRoute(); + 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.getFlowMatchInvokers("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 73b7dfcd42..7af8bb0d54 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 @@ -21,7 +21,6 @@ import com.huaweicloud.sermant.router.common.utils.CollectionUtils; import com.huaweicloud.sermant.router.config.entity.Match; import com.huaweicloud.sermant.router.config.entity.Policy; -import com.huaweicloud.sermant.router.config.entity.Route; import com.huaweicloud.sermant.router.config.entity.Rule; import com.huaweicloud.sermant.router.config.utils.PolicyEventUtils; import com.huaweicloud.sermant.router.config.utils.RuleUtils; @@ -74,9 +73,35 @@ public AbstractRuleStrategy(String source, InstanceStrategy getMatchInstances(String serviceName, List instances, List routes) { - RouteResult result = RuleUtils.getTargetTags(routes); - return getInstances(getStrategy(result.isMatch()), result.getTags(), serviceName, instances, true); + public List getFlowMatchInstances(String serviceName, List instances, Rule rule) { + RouteResult result = RuleUtils.getTargetTags(rule.getRoute()); + if (CollectionUtils.isEmpty(rule.getFallback())) { + return getInstances(getStrategy(result.isMatch()), result.getTags(), serviceName, instances, true); + } + if (result.isMatch()) { + // route命中标签,fallback有设置路由规则时,仅返回匹配的实例,如果存在直接返回 + List routeInstances = getInstances(getStrategy(result.isMatch()), result.getTags(), serviceName, + instances, false); + if (!CollectionUtils.isEmpty(routeInstances)) { + return routeInstances; + } + } + + // route设置的目标标签未匹配实例时,fallback有设置路由,通过fallback路由目标标签实例 + RouteResult fallback = RuleUtils.getTargetTags(rule.getFallback()); + if (fallback.isMatch()) { + List fallbackInstances = getInstances(getStrategy(fallback.isMatch()), fallback.getTags(), serviceName, + instances, false); + + // fallback中设置了路由规则命中routeTag,且有对应的实例匹配则按fallback路由规则选中实例,返回对应实例 + if (!CollectionUtils.isEmpty(fallbackInstances)) { + return fallbackInstances; + } + } + + // 结合上面result.isMatch()为true逻辑,如果为true未能匹配实例,直接返回所有实例,反之通过mismatch处理 + return result.isMatch() ? instances + : 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 785ed1e9b9..65b4351675 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 @@ -16,7 +16,6 @@ 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; @@ -35,10 +34,10 @@ public interface RuleStrategy { * * @param serviceName 服务名 * @param instances 实例列表 - * @param routes 路由规则 + * @param rule 路由规则 * @return 路由过滤后的实例 */ - List getMatchInstances(String serviceName, List instances, List routes); + List getFlowMatchInstances(String serviceName, List instances, Rule rule); /** * 选取路由的实例 diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java index 16b132ca52..86743c9f24 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/utils/RuleUtils.java @@ -274,6 +274,12 @@ public static void removeInvalidRules(List list, boolean isReplaceDa // 去掉无效的路由和修复同标签规则的路由 removeInvalidRoute(routes, kind, isReplaceDash, isAppendPrefix); + List fallback = rule.getFallback(); + if (!CollectionUtils.isEmpty(fallback)) { + // 去掉无效的路由和修复同标签规则的路由 + removeInvalidRoute(fallback, kind, isReplaceDash, isAppendPrefix); + } + // 去掉全是无效路由的规则 if (CollectionUtils.isEmpty(routes)) { LOGGER.warning("Routes are invalid, rule will be removed."); diff --git a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/handler/FlowRouteHandler.java b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/handler/FlowRouteHandler.java index a3e33aaaef..b3214196f4 100644 --- a/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/handler/FlowRouteHandler.java +++ b/sermant-plugins/sermant-router/spring-router-service/src/main/java/com/huaweicloud/sermant/router/spring/handler/FlowRouteHandler.java @@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; /** * 流量匹配方式的路由处理器 @@ -140,9 +141,9 @@ private List getTargetInstancesByRules(String targetName, List i if (CollectionUtils.isEmpty(rules)) { return instances; } - List routes = getRoutes(rules, header); - if (!CollectionUtils.isEmpty(routes)) { - return RuleStrategyHandler.INSTANCE.getMatchInstances(targetName, instances, routes); + Optional ruleOptional = getRule(rules, header); + if (ruleOptional.isPresent()) { + return RuleStrategyHandler.INSTANCE.getFlowMatchInstances(targetName, instances, ruleOptional.get()); } return RuleStrategyHandler.INSTANCE .getMismatchInstances(targetName, instances, RuleUtils.getTags(rules), true); @@ -155,14 +156,14 @@ private List getTargetInstancesByRules(String targetName, List i * @param header header * @return 匹配的路由 */ - private List getRoutes(List list, Map> header) { + private Optional getRule(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 List getRoutes(Map> header, Rule rule) { 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 96afdc7db8..948b4cc3e5 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 @@ -16,7 +16,6 @@ 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; @@ -65,11 +64,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); + public List getFlowMatchInstances(String serviceName, List instances, Rule rule) { + return getRuleStrategy(instances).getFlowMatchInstances(serviceName, instances, 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 107d2f7974..79cef4204c 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.getFlowMatchInstances("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.getFlowMatchInstances("foo", instances, rule); Assert.assertEquals(1, matchInstances.size()); Assert.assertEquals(instance2, matchInstances.get(0)); @@ -114,4 +120,92 @@ public void testMismatchV1() { Assert.assertEquals(1, mismatchInstances.size()); Assert.assertEquals(instance2, mismatchInstances.get(0)); } + + /** + * rule中route有命中tag,但是没有符合版本的实例,invoker命中fallback版本实例的情况 + */ + @Test + public void testMatchV1Fallback() { + setFallbackRoute(); + + 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.getFlowMatchInstances("foo", instances, rule); + Assert.assertEquals(100, routes.get(0).getWeight().intValue()); + Assert.assertEquals(1, matchInvoker.size()); + Assert.assertEquals(instance1, matchInvoker.get(0)); + } + + private void setFallbackRoute() { + List fallback = new ArrayList<>(); + Map tags = new HashMap<>(); + tags.put(RouterConstant.VERSION, "0.0.3"); + Route route = new Route(); + route.setTags(tags); + route.setWeight(100); + fallback.add(route); + rule.setFallback(fallback); + } + + /** + * rule中设置route、fallback,且权重均有命中tag,但是invoker均未命中版本实例的情况 + */ + @Test + public void testSpringV1NotMathRouteFallback() { + setFallbackRoute(); + + 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.getFlowMatchInstances("foo", instances, rule); + Assert.assertEquals(2, matchInvoker.size()); + } + + /** + * rule中设置routes但权重计算未命中,invoker命中fallback版本实例的情况 + */ + @Test + public void testSpringV1MathFallback() { + setFallbackRoute(); + 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.getFlowMatchInstances("foo", instances, rule); + Assert.assertEquals(1, matchInvoker.size()); + Assert.assertEquals(instance2, matchInvoker.get(0)); + } + + /** + * rule中设置routes但权重计算未命中,同时fallback也未命中实例,invoker返回未设置规则版本号版本实例的情况 + */ + @Test + public void testSpringV1BothNotMathFallbackRoute() { + setFallbackRoute(); + 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.getFlowMatchInstances("foo", instances, rule); + Assert.assertEquals(1, matchInvoker.size()); + Assert.assertEquals(instance2, matchInvoker.get(0)); + } } \ No newline at end of file