diff --git a/sermant-plugins/sermant-router/config/config.yaml b/sermant-plugins/sermant-router/config/config.yaml index 5bc03adf43..9a815f6f6c 100644 --- a/sermant-plugins/sermant-router/config/config.yaml +++ b/sermant-plugins/sermant-router/config/config.yaml @@ -13,6 +13,8 @@ router.plugin: request-tags: [] # 需要解析的请求头的tag parse-header-tag: '' + # 区域路由默认策略,全部生效:ALL 全不生效:NONE 白名单策略:WHITE 黑名单策略:BLACK + zone-router-default-strategy: NONE transmit.plugin: # 是否在直接new Thread时传递标签 enabled-thread: true 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 7c7a160b8b..649a80b301 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 @@ -188,7 +188,7 @@ private void putAttachment(Object invocation) { private List getTargetInvokersByRules(List invokers, Object invocation, Map queryMap, String targetService, String serviceInterface) { RouterConfiguration configuration = ConfigCache.getLabel(RouterConstant.DUBBO_CACHE_NAME); - if (RouterConfiguration.isInValid(configuration)) { + if (RouterConfiguration.isInValid(configuration, targetService)) { return invokers; } String interfaceName = getGroup(queryMap) + "/" + serviceInterface + POINT diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/RouterConfig.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/RouterConfig.java index 231eb8e8b5..e6fa45da2e 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/RouterConfig.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/config/RouterConfig.java @@ -93,6 +93,12 @@ public class RouterConfig implements PluginConfig { @ConfigFieldKey("parse-header-tag") private String parseHeaderTag; + /** + * 区域路由默认策略 + */ + @ConfigFieldKey("zone-router-default-strategy") + private String zoneRouterDefaultStrategy = "NONE"; + /** * 构造方法 */ @@ -195,4 +201,12 @@ public String getParseHeaderTag() { public void setParseHeaderTag(String parseHeaderTag) { this.parseHeaderTag = parseHeaderTag; } + + public String getZoneRouterDefaultStrategy() { + return zoneRouterDefaultStrategy; + } + + public void setZoneRouterDefaultStrategy(String zoneRouterDefaultStrategy) { + this.zoneRouterDefaultStrategy = zoneRouterDefaultStrategy; + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java index b803c1159e..df402522a8 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java @@ -88,6 +88,11 @@ public class RouterConstant { */ public static final String ZONE_KEY = "service.meta.zone"; + /** + * 全局标签路由key + */ + public static final String GLOBAL_ROUTER_KEY = "servicecomb.globalRouteRule"; + private RouterConstant() { } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-common/pom.xml b/sermant-plugins/sermant-router/router-config-common/pom.xml index ae4826fb70..a649dc6be5 100644 --- a/sermant-plugins/sermant-router/router-config-common/pom.xml +++ b/sermant-plugins/sermant-router/router-config-common/pom.xml @@ -39,5 +39,15 @@ junit test + + org.mockito + mockito-core + test + + + org.mockito + mockito-inline + test + \ 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/EnabledStrategy.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategy.java index da53821c41..c2ca60b9e1 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategy.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategy.java @@ -16,8 +16,12 @@ package com.huaweicloud.sermant.router.config.entity; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.RouterConfig; + import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.concurrent.CopyOnWriteArrayList; /** @@ -32,10 +36,24 @@ public class EnabledStrategy { */ private final List value = new CopyOnWriteArrayList<>(); + /** + * 默认策略 + */ + private final Strategy defaultStrategy; + /** * 开启策略 */ - private Strategy strategy = Strategy.NONE; + private Strategy strategy; + + /** + * 构造方法 + */ + public EnabledStrategy() { + RouterConfig routerConfig = PluginConfigManager.getPluginConfig(RouterConfig.class); + defaultStrategy = Strategy.valueOf(routerConfig.getZoneRouterDefaultStrategy().toUpperCase(Locale.ROOT)); + strategy = defaultStrategy; + } public Strategy getStrategy() { return strategy; @@ -49,7 +67,7 @@ public List getValue() { * 重置配置 */ public void reset() { - reset(Strategy.NONE, Collections.emptyList()); + reset(defaultStrategy, Collections.emptyList()); } /** diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/RouterConfiguration.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/RouterConfiguration.java index 763649ef9c..b6c3b3fbbd 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/RouterConfiguration.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/RouterConfiguration.java @@ -18,9 +18,11 @@ import com.huaweicloud.sermant.router.common.utils.CollectionUtils; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; /** * 路由标签 @@ -34,10 +36,32 @@ public class RouterConfiguration { */ private final Map> routeRule = new ConcurrentHashMap<>(); + /** + * 全局路由规则 + */ + private final List globalRules = new CopyOnWriteArrayList<>(); + public Map> getRouteRule() { return routeRule; } + public List getGlobalRules() { + return globalRules; + } + + /** + * 获取指定服务的路由规则 + * + * @param serviceName 服务名 + * @return 路由规则 + */ + public List getRules(String serviceName) { + if (CollectionUtils.isEmpty(routeRule) && CollectionUtils.isEmpty(globalRules)) { + return Collections.emptyList(); + } + return routeRule.getOrDefault(serviceName, globalRules); + } + /** * 重置路由规则 * @@ -48,6 +72,16 @@ public void resetRouteRule(Map> map) { routeRule.putAll(map); } + /** + * 重置全局路由规则 + * + * @param rules 全局路由规则 + */ + public void resetGlobalRules(List rules) { + globalRules.clear(); + globalRules.addAll(rules); + } + /** * 路由规则是否无效 * @@ -55,6 +89,18 @@ public void resetRouteRule(Map> map) { * @return 是否无效 */ public static boolean isInValid(RouterConfiguration configuration) { - return configuration == null || CollectionUtils.isEmpty(configuration.getRouteRule()); + return configuration == null || (CollectionUtils.isEmpty(configuration.getRouteRule()) + && CollectionUtils.isEmpty(configuration.getGlobalRules())); + } + + /** + * 路由规则是否无效 + * + * @param configuration 路由规则 + * @param serviceName 服务名 + * @return 是否无效 + */ + public static boolean isInValid(RouterConfiguration configuration, String serviceName) { + return configuration == null || CollectionUtils.isEmpty(configuration.getRules(serviceName)); } } \ No newline at end of file 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 ae7844c591..0205b7ebb3 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 @@ -71,14 +71,7 @@ private RuleUtils() { */ public static List getRules(RouterConfiguration configuration, String targetService, String path, String serviceName) { - if (RouterConfiguration.isInValid(configuration)) { - return Collections.emptyList(); - } - Map> routeRule = configuration.getRouteRule(); - if (CollectionUtils.isEmpty(routeRule)) { - return Collections.emptyList(); - } - List rules = routeRule.get(targetService); + List rules = configuration.getRules(targetService); if (CollectionUtils.isEmpty(rules)) { return Collections.emptyList(); } @@ -125,6 +118,7 @@ public static void initMatchKeys(RouterConfiguration configuration) { for (List rules : routeRules.values()) { addKeys(rules, MATCH_KEYS); } + addKeys(configuration.getGlobalRules(), MATCH_KEYS); } /** diff --git a/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategyTest.java b/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategyTest.java index 0e2c0a74a8..888b128b8d 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategyTest.java +++ b/sermant-plugins/sermant-router/router-config-common/src/test/java/com/huaweicloud/sermant/router/config/entity/EnabledStrategyTest.java @@ -16,8 +16,15 @@ package com.huaweicloud.sermant.router.config.entity; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; +import com.huaweicloud.sermant.router.common.config.RouterConfig; + +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import java.util.Collections; @@ -28,6 +35,26 @@ * @since 2022-10-10 */ public class EnabledStrategyTest { + private static MockedStatic mockPluginConfigManager; + + /** + * 初始化 + */ + @BeforeClass + public static void init() { + RouterConfig config = new RouterConfig(); + mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(RouterConfig.class)).thenReturn(config); + } + + /** + * 清除mock + */ + @AfterClass + public static void clear() { + mockPluginConfigManager.close(); + } + /** * 测试reset方法 diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandler.java new file mode 100644 index 0000000000..c5e3252342 --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandler.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huaweicloud.sermant.router.config.handler; + +import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEvent; +import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEventType; +import com.huaweicloud.sermant.core.utils.StringUtils; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; +import com.huaweicloud.sermant.router.common.utils.CollectionUtils; +import com.huaweicloud.sermant.router.config.cache.ConfigCache; +import com.huaweicloud.sermant.router.config.entity.RouterConfiguration; +import com.huaweicloud.sermant.router.config.entity.Rule; +import com.huaweicloud.sermant.router.config.utils.RuleUtils; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * 全局标签路由 + * + * @author provenceee + * @since 2023-09-20 + */ +public class GlobalConfigHandler extends AbstractConfigHandler { + @Override + public void handle(DynamicConfigEvent event, String cacheName) { + RouterConfiguration configuration = ConfigCache.getLabel(cacheName); + if (event.getEventType() == DynamicConfigEventType.DELETE) { + configuration.resetGlobalRules(Collections.emptyList()); + RuleUtils.initMatchKeys(configuration); + return; + } + List rules = JSONArray.parseArray(JSONObject.toJSONString(getRuleMap(event)), Rule.class); + RuleUtils.removeInvalidRules(rules); + if (CollectionUtils.isEmpty(rules)) { + configuration.resetGlobalRules(Collections.emptyList()); + } else { + rules.sort((o1, o2) -> o2.getPrecedence() - o1.getPrecedence()); + configuration.resetGlobalRules(rules); + } + RuleUtils.initMatchKeys(configuration); + } + + @Override + public boolean shouldHandle(String key) { + return RouterConstant.GLOBAL_ROUTER_KEY.equals(key); + } + + private List> getRuleMap(DynamicConfigEvent event) { + String content = event.getContent(); + if (StringUtils.isBlank(content)) { + return Collections.emptyList(); + } + Map>> ruleMap = yaml.load(content); + return ruleMap.get(RouterConstant.GLOBAL_ROUTER_KEY); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/listener/RouterConfigListener.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/listener/RouterConfigListener.java index d6dc333646..bf83bac614 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/listener/RouterConfigListener.java +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/listener/RouterConfigListener.java @@ -21,6 +21,7 @@ import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigListener; import com.huaweicloud.sermant.router.config.handler.AbstractConfigHandler; import com.huaweicloud.sermant.router.config.handler.EnabledStrategyHandler; +import com.huaweicloud.sermant.router.config.handler.GlobalConfigHandler; import com.huaweicloud.sermant.router.config.handler.RouterConfigHandler; import com.huaweicloud.sermant.router.config.handler.ServiceConfigHandler; @@ -53,6 +54,7 @@ public RouterConfigListener(String cacheName) { this.handlers.add(new RouterConfigHandler()); this.handlers.add(new ServiceConfigHandler()); this.handlers.add(new EnabledStrategyHandler()); + this.handlers.add(new GlobalConfigHandler()); } @Override diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/EnabledStrategyHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/EnabledStrategyHandlerTest.java index 25a9d33895..fe08fffc3f 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/EnabledStrategyHandlerTest.java +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/EnabledStrategyHandlerTest.java @@ -16,15 +16,21 @@ package com.huaweicloud.sermant.router.config.handler; +import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; import com.huaweicloud.sermant.core.plugin.subscribe.processor.OrderConfigEvent; import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEvent; import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEventType; +import com.huaweicloud.sermant.router.common.config.RouterConfig; import com.huaweicloud.sermant.router.config.cache.ConfigCache; import com.huaweicloud.sermant.router.config.entity.EnabledStrategy; import com.huaweicloud.sermant.router.config.entity.Strategy; +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import java.util.Collections; import java.util.HashMap; @@ -37,8 +43,28 @@ * @since 2022-10-10 */ public class EnabledStrategyHandlerTest { + private static MockedStatic mockPluginConfigManager; + private final AbstractConfigHandler handler; + /** + * 初始化 + */ + @BeforeClass + public static void init() { + RouterConfig config = new RouterConfig(); + mockPluginConfigManager = Mockito.mockStatic(PluginConfigManager.class); + mockPluginConfigManager.when(() -> PluginConfigManager.getPluginConfig(RouterConfig.class)).thenReturn(config); + } + + /** + * 清除mock + */ + @AfterClass + public static void clear() { + mockPluginConfigManager.close(); + } + public EnabledStrategyHandlerTest() { this.handler = new EnabledStrategyHandler(); } 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 eb54b823f0..18a38a1b88 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 @@ -92,7 +92,7 @@ private boolean shouldHandle(List instances) { private List getTargetInstancesByRules(String targetName, List instances, String path, Map> header) { RouterConfiguration configuration = ConfigCache.getLabel(RouterConstant.SPRING_CACHE_NAME); - if (RouterConfiguration.isInValid(configuration)) { + if (RouterConfiguration.isInValid(configuration, targetName)) { return instances; } List rules = RuleUtils.getRules(configuration, targetName, path, AppCache.INSTANCE.getAppName());