From 9841121c05fef2e7ddd98a9b64b1deb8adc128a2 Mon Sep 17 00:00:00 2001 From: provenceee <83857838+provenceee@users.noreply.github.com> Date: Fri, 12 Jan 2024 18:27:40 +0800 Subject: [PATCH] =?UTF-8?q?*=E4=BF=AE=E6=94=B9=E5=85=BC=E5=AE=B9=E6=80=A7?= 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> --- .../common/constants/RouterConstant.java | 42 +++- .../config/entity/RouterConfiguration.java | 63 +++++ .../router/config/utils/RuleUtils.java | 96 +++---- .../config/handler/AbstractConfigHandler.java | 18 +- .../config/handler/AbstractHandler.java | 46 ++++ .../config/handler/GlobalConfigHandler.java | 4 +- .../config/handler/RouterConfigHandler.java | 4 +- .../config/handler/ServiceConfigHandler.java | 4 +- .../handler/kind/AbstractKindHandler.java | 234 ++++++++++++++++++ .../config/handler/kind/FlowKindHandler.java | 54 ++++ .../config/handler/kind/LaneKindHandler.java | 54 ++++ .../config/handler/kind/TagKindHandler.java | 54 ++++ .../config/listener/RouterConfigListener.java | 12 +- .../handler/GlobalConfigHandlerTest.java | 4 +- .../handler/RouterConfigHandlerTest.java | 6 +- .../handler/ServiceConfigHandlerTest.java | 6 +- .../handler/kind/FlowKindHandlerTest.java | 47 ++++ .../handler/kind/LaneKindHandlerTest.java | 47 ++++ .../handler/kind/TagKindHandlerTest.java | 48 ++++ 19 files changed, 774 insertions(+), 69 deletions(-) create mode 100644 sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractHandler.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/AbstractKindHandler.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandler.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandler.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandler.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandlerTest.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandlerTest.java create mode 100644 sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandlerTest.java 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 04573504ef..6e3f447c60 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 @@ -47,12 +47,12 @@ public class RouterConstant { public static final String IS_METHOD_SUFFIX = "()"; /** - * 标签路由key前缀 + * 流量路由key前缀 */ public static final String ROUTER_KEY_PREFIX = "servicecomb.routeRule"; /** - * 标签路由全局规则key + * 流量路由全局规则key */ public static final String GLOBAL_ROUTER_KEY = "servicecomb.globalRouteRule"; @@ -156,6 +156,44 @@ public class RouterConstant { */ public static final String ZONE = "zone"; + /** + * 标签路由key前缀 + */ + public static final String TAG_KEY_PREFIX = "servicecomb.tagRule"; + + /** + * 标签路由全局规则key + */ + public static final String GLOBAL_TAG_KEY = "servicecomb.globalTagRule"; + + /** + * 泳道key前缀 + */ + public static final String LANE_KEY_PREFIX = "servicecomb.laneRule"; + + /** + * 泳道全局规则key + */ + public static final String GLOBAL_LANE_KEY = "servicecomb.globalLaneRule"; + + /** + * 全量服务级兼容的key + */ + public static final List COMPATIBILITY_KEY_LIST = Arrays.asList(ROUTER_KEY_PREFIX, TAG_KEY_PREFIX, + LANE_KEY_PREFIX); + + /** + * 全局级兼容的key + */ + public static final List GLOBAL_COMPATIBILITY_KEY_LIST = Arrays.asList(GLOBAL_ROUTER_KEY, GLOBAL_TAG_KEY, + GLOBAL_LANE_KEY); + + /** + * 服务级兼容的key + */ + public static final List SERVICE_COMPATIBILITY_KEY_LIST = Arrays.asList(ROUTER_KEY_PREFIX + POINT, + TAG_KEY_PREFIX + POINT, LANE_KEY_PREFIX + POINT); + private RouterConstant() { } } \ 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/RouterConfiguration.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/entity/RouterConfiguration.java index c4b186bf2d..a753888799 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 @@ -102,6 +102,20 @@ public void updateServiceRule(String serviceName, List entireRules) } } + /** + * 按类型更新服务粒度的路由规则 + * + * @param serviceName 服务名 + * @param entireRule 规则 + */ + public void updateServiceRule(String serviceName, EntireRule entireRule) { + Map> ruleList = rules.computeIfAbsent(entireRule.getKind(), + key -> new ConcurrentHashMap<>()); + ruleList.put(serviceName, entireRule.getRules()); + LOGGER.info(String.format(Locale.ROOT, "Rule for %s has been updated: %s ", serviceName, + JSONObject.toJSONString(entireRule))); + } + /** * 移除服务的路由规则 * @@ -123,6 +137,20 @@ public void removeServiceRule(String serviceName) { LOGGER.info(String.format(Locale.ROOT, "All rules for %s have been removed! ", serviceName)); } + /** + * 移除服务的路由规则 + * + * @param serviceName 服务名 + * @param kind 规则类型 + */ + public void removeServiceRule(String serviceName, String kind) { + Map> ruleList = rules.get(kind); + if (!CollectionUtils.isEmpty(ruleList)) { + ruleList.remove(serviceName); + } + LOGGER.info(String.format(Locale.ROOT, "%s rules for %s have been removed! ", kind, serviceName)); + } + /** * 重置路由规则 * @@ -139,6 +167,26 @@ public void resetRouteRule(Map> map) { } } + /** + * 重置路由规则 + * + * @param kind 规则类型 + * @param map 路由规则 + */ + public void resetRouteRule(String kind, Map map) { + if (CollectionUtils.isEmpty(map)) { + rules.remove(kind); + } else { + for (Map.Entry ruleEntry : map.entrySet()) { + EntireRule entireRule = ruleEntry.getValue(); + Map> serviceRuleMap = rules.compute(kind, (key, value) -> new ConcurrentHashMap<>()); + serviceRuleMap.put(ruleEntry.getKey(), entireRule.getRules()); + } + } + LOGGER.info(String.format(Locale.ROOT, "Service rules have been updated: %s", + JSONObject.toJSONString(map))); + } + /** * 重置全局路由规则 * @@ -153,6 +201,21 @@ public void resetGlobalRule(List list) { JSONObject.toJSONString(list))); } + /** + * 重置全局路由规则 + * + * @param entireRule 路由规则 + */ + public void resetGlobalRule(EntireRule entireRule) { + if (CollectionUtils.isEmpty(entireRule.getRules())) { + globalRules.remove(entireRule.getKind()); + } else { + globalRules.put(entireRule.getKind(), entireRule.getRules()); + } + LOGGER.info(String.format(Locale.ROOT, "Global rules have been updated: %s", + JSONObject.toJSONString(entireRule))); + } + /** * 路由规则是否无效 * 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 86743c9f24..89b8450cc0 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 @@ -258,59 +258,71 @@ public static void removeInvalidRules(List list, boolean isReplaceDa entireIterator.remove(); continue; } + removeInvalidRules(entireRule.getKind(), entireRule.getRules(), isReplaceDash, isAppendPrefix); - Iterator ruleIterator = entireRule.getRules().iterator(); - while (ruleIterator.hasNext()) { - Rule rule = ruleIterator.next(); - List routes = rule.getRoute(); + // 去掉全是无效规则的配置 + if (CollectionUtils.isEmpty(entireRule.getRules())) { + entireIterator.remove(); + } + } + } - // 去掉没有配置路由的规则 - if (CollectionUtils.isEmpty(routes)) { - LOGGER.warning("Routes are empty, rule will be removed."); - ruleIterator.remove(); - continue; - } + /** + * 去掉无效的规则 + * + * @param kind 规则类型 + * @param rules 规则 + * @param isReplaceDash 是否需要把"-"替换成"." + * @param isAppendPrefix 元数据的key值是否需要加上前缀 + */ + public static void removeInvalidRules(String kind, List rules, boolean isReplaceDash, + boolean isAppendPrefix) { + Iterator ruleIterator = rules.iterator(); + while (ruleIterator.hasNext()) { + Rule rule = ruleIterator.next(); + List routes = rule.getRoute(); - // 去掉无效的路由和修复同标签规则的路由 - removeInvalidRoute(routes, kind, isReplaceDash, isAppendPrefix); + // 去掉没有配置路由的规则 + if (CollectionUtils.isEmpty(routes)) { + LOGGER.warning("Routes are empty, rule will be removed."); + ruleIterator.remove(); + continue; + } - List fallback = rule.getFallback(); - if (!CollectionUtils.isEmpty(fallback)) { - // 去掉无效的路由和修复同标签规则的路由 - removeInvalidRoute(fallback, kind, isReplaceDash, isAppendPrefix); - } + // 去掉无效的路由和修复同标签规则的路由 + removeInvalidRoute(routes, kind, isReplaceDash, isAppendPrefix); - // 去掉全是无效路由的规则 - if (CollectionUtils.isEmpty(routes)) { - LOGGER.warning("Routes are invalid, rule will be removed."); - ruleIterator.remove(); - continue; - } + List fallback = rule.getFallback(); + if (!CollectionUtils.isEmpty(fallback)) { + // 去掉无效的路由和修复同标签规则的路由 + removeInvalidRoute(fallback, kind, isReplaceDash, isAppendPrefix); + } - if (RouterConstant.FLOW_MATCH_KIND.equals(kind)) { - // 去掉无效的规则 - removeInvalidMatch(rule.getMatch()); + // 去掉全是无效路由的规则 + if (CollectionUtils.isEmpty(routes)) { + LOGGER.warning("Routes are invalid, rule will be removed."); + ruleIterator.remove(); + continue; + } - // 无attachments规则,将headers规则更新到attachments规则 - setAttachmentsByHeaders(rule.getMatch()); - continue; - } + if (RouterConstant.FLOW_MATCH_KIND.equals(kind)) { + // 去掉无效的规则 + removeInvalidMatch(rule.getMatch()); - if (RouterConstant.TAG_MATCH_KIND.equals(kind)) { - // 去掉无效的规则 - removeInvalidTagMatch(rule.getMatch(), isAppendPrefix); - continue; - } + // 无attachments规则,将headers规则更新到attachments规则 + setAttachmentsByHeaders(rule.getMatch()); + continue; + } - if (RouterConstant.LANE_MATCH_KIND.equals(kind)) { - // 去掉无效的规则 - removeInvalidLaneMatch(rule.getMatch()); - } + if (RouterConstant.TAG_MATCH_KIND.equals(kind)) { + // 去掉无效的规则 + removeInvalidTagMatch(rule.getMatch(), isAppendPrefix); + continue; } - // 去掉全是无效规则的配置 - if (CollectionUtils.isEmpty(entireRule.getRules())) { - entireIterator.remove(); + if (RouterConstant.LANE_MATCH_KIND.equals(kind)) { + // 去掉无效的规则 + removeInvalidLaneMatch(rule.getMatch()); } } } diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractConfigHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractConfigHandler.java index 630ddaf056..12e5ad1143 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractConfigHandler.java +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractConfigHandler.java @@ -16,7 +16,7 @@ package com.huaweicloud.sermant.router.config.handler; -import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEvent; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; import com.huaweicloud.sermant.router.config.common.SafeConstructor; import org.yaml.snakeyaml.Yaml; @@ -27,7 +27,7 @@ * @author provenceee * @since 2022-08-09 */ -public abstract class AbstractConfigHandler { +public abstract class AbstractConfigHandler implements AbstractHandler { /** * yaml */ @@ -40,19 +40,15 @@ public AbstractConfigHandler() { this.yaml = new Yaml(new SafeConstructor(null)); } - /** - * 路由配置处理 - * - * @param event 配置监听事件 - * @param cacheName 缓存名 - */ - public abstract void handle(DynamicConfigEvent event, String cacheName); - /** * 是否需要处理 * * @param key 配置key + * @param content 配置内容 * @return 是否需要处理 */ - public abstract boolean shouldHandle(String key); + @Override + public boolean shouldHandle(String key, String content) { + return RouterConstant.MATCH_KIND_LIST.stream().anyMatch(content::contains); + } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractHandler.java new file mode 100644 index 0000000000..707e5b6e54 --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/AbstractHandler.java @@ -0,0 +1,46 @@ +/* + * + * * Copyright (C) 2024-2024 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; + +/** + * 处理器接口 + * + * @author provenceee + * @since 2024-01-16 + */ +public interface AbstractHandler { + /** + * 配置处理 + * + * @param event 配置监听事件 + * @param cacheName 缓存名 + */ + void handle(DynamicConfigEvent event, String cacheName); + + /** + * 是否需要处理 + * + * @param key 配置key + * @param content 配置内容 + * @return 是否需要处理 + */ + boolean shouldHandle(String key, String content); +} 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 index 4ad3774990..a65d3bf3cb 100644 --- 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 @@ -69,8 +69,8 @@ public void handle(DynamicConfigEvent event, String cacheName) { } @Override - public boolean shouldHandle(String key) { - return RouterConstant.GLOBAL_ROUTER_KEY.equals(key); + public boolean shouldHandle(String key, String content) { + return super.shouldHandle(key, content) && RouterConstant.GLOBAL_ROUTER_KEY.equals(key); } private List> getRule(DynamicConfigEvent event) { diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandler.java index e3ce15fd50..7e7bf466e7 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandler.java +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandler.java @@ -77,8 +77,8 @@ public void handle(DynamicConfigEvent event, String cacheName) { } @Override - public boolean shouldHandle(String key) { - return RouterConstant.ROUTER_KEY_PREFIX.equals(key); + public boolean shouldHandle(String key, String content) { + return super.shouldHandle(key, content) && RouterConstant.ROUTER_KEY_PREFIX.equals(key); } private Map> getRouteRuleMap(DynamicConfigEvent event) { diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandler.java index 63600d05df..c38bdaddf4 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandler.java +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandler.java @@ -73,8 +73,8 @@ public void handle(DynamicConfigEvent event, String cacheName) { } @Override - public boolean shouldHandle(String key) { - return key.startsWith(RouterConstant.ROUTER_KEY_PREFIX + POINT); + public boolean shouldHandle(String key, String content) { + return super.shouldHandle(key, content) && key.startsWith(RouterConstant.ROUTER_KEY_PREFIX + POINT); } private List> getRule(DynamicConfigEvent event, String serviceName) { diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/AbstractKindHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/AbstractKindHandler.java new file mode 100644 index 0000000000..0e77ec6ac4 --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/AbstractKindHandler.java @@ -0,0 +1,234 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +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.event.RouterEventCollector; +import com.huaweicloud.sermant.router.common.utils.CollectionUtils; +import com.huaweicloud.sermant.router.config.cache.ConfigCache; +import com.huaweicloud.sermant.router.config.common.SafeConstructor; +import com.huaweicloud.sermant.router.config.entity.EntireRule; +import com.huaweicloud.sermant.router.config.entity.RouterConfiguration; +import com.huaweicloud.sermant.router.config.entity.Rule; +import com.huaweicloud.sermant.router.config.handler.AbstractHandler; +import com.huaweicloud.sermant.router.config.utils.RuleUtils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import org.yaml.snakeyaml.Yaml; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * 配置类型处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public abstract class AbstractKindHandler implements AbstractHandler { + /** + * yaml + */ + protected final Yaml yaml; + + /** + * 构造方法 + */ + public AbstractKindHandler() { + this.yaml = new Yaml(new SafeConstructor(null)); + } + + /** + * 路由配置类型处理 + * + * @param event 配置监听事件 + * @param cacheName 缓存名 + */ + @Override + public void handle(DynamicConfigEvent event, String cacheName) { + if (RouterConstant.GLOBAL_COMPATIBILITY_KEY_LIST.contains(event.getKey())) { + handleGlobalRules(event, cacheName, getKind()); + } else if (RouterConstant.COMPATIBILITY_KEY_LIST.contains(event.getKey())) { + handleRouterRules(event, cacheName, getKind()); + } else { + handleServiceRules(event, cacheName, getKind()); + } + } + + /** + * 是否需要兼容性处理 + * + * @param key 配置key + * @param content 配置内容 + * @return 是否需要处理 + */ + @Override + public boolean shouldHandle(String key, String content) { + return RouterConstant.MATCH_KIND_LIST.stream().noneMatch(content::contains); + } + + /** + * 获取类型 + * + * @return 类型 + */ + public abstract String getKind(); + + /** + * 解析全局配置 + * + * @param event 事件 + * @param cacheName 缓存key + * @param kind 配置类型 + */ + private void handleGlobalRules(DynamicConfigEvent event, String cacheName, String kind) { + RouterConfiguration configuration = ConfigCache.getLabel(cacheName); + if (event.getEventType() == DynamicConfigEventType.DELETE) { + configuration.resetGlobalRule(getEntireRule(kind, null)); + RuleUtils.initMatchKeys(configuration); + RouterEventCollector.getInstance() + .collectGlobalRouteRuleEvent(JSON.toJSONString(configuration.getGlobalRule())); + return; + } + + List list = JSONArray.parseArray(JSONObject.toJSONString(getRules(event)), Rule.class); + RuleUtils.removeInvalidRules(kind, list, RouterConstant.DUBBO_CACHE_NAME.equals(cacheName), + RouterConstant.DUBBO_CACHE_NAME.equals(cacheName)); + if (!CollectionUtils.isEmpty(list)) { + list.sort((o1, o2) -> o2.getPrecedence() - o1.getPrecedence()); + } + configuration.resetGlobalRule(getEntireRule(kind, list)); + RuleUtils.initMatchKeys(configuration); + RouterEventCollector.getInstance() + .collectGlobalRouteRuleEvent(JSON.toJSONString(configuration.getGlobalRule())); + } + + /** + * 解析服务级配置(全级) + * + * @param event 事件 + * @param cacheName 缓存key + * @param kind 配置类型 + */ + private void handleRouterRules(DynamicConfigEvent event, String cacheName, String kind) { + RouterConfiguration configuration = ConfigCache.getLabel(cacheName); + if (event.getEventType() == DynamicConfigEventType.DELETE) { + configuration.resetRouteRule(kind, Collections.emptyMap()); + RuleUtils.initKeys(configuration); + RouterEventCollector.getInstance() + .collectServiceRouteRuleEvent(JSON.toJSONString(configuration.getRouteRule())); + return; + } + Map routeRuleMap = getRouteRuleMap(event); + Map routeRule = new HashMap<>(); + for (Entry entry : routeRuleMap.entrySet()) { + List> routeRuleList = yaml.load(entry.getValue()); + if (CollectionUtils.isEmpty(routeRuleList)) { + continue; + } + List list = JSONArray.parseArray(JSONObject.toJSONString(routeRuleList), Rule.class); + RuleUtils.removeInvalidRules(kind, list, RouterConstant.DUBBO_CACHE_NAME.equals(cacheName), + RouterConstant.DUBBO_CACHE_NAME.equals(cacheName)); + if (!CollectionUtils.isEmpty(list)) { + list.sort((o1, o2) -> o2.getPrecedence() - o1.getPrecedence()); + routeRule.put(entry.getKey(), getEntireRule(kind, list)); + } + } + configuration.resetRouteRule(kind, routeRule); + RuleUtils.initKeys(configuration); + RouterEventCollector.getInstance() + .collectServiceRouteRuleEvent(JSON.toJSONString(configuration.getRouteRule())); + } + + /** + * 解析服务级配置 + * + * @param event 事件 + * @param cacheName 缓存key + * @param kind 配置类型 + */ + private void handleServiceRules(DynamicConfigEvent event, String cacheName, String kind) { + RouterConfiguration configuration = ConfigCache.getLabel(cacheName); + if (event.getEventType() == DynamicConfigEventType.DELETE) { + String serviceName = event.getKey().substring(RouterConstant.ROUTER_KEY_PREFIX.length() + 1); + configuration.removeServiceRule(serviceName, kind); + RuleUtils.initKeys(configuration); + RouterEventCollector.getInstance() + .collectServiceRouteRuleEvent(JSON.toJSONString(configuration.getRouteRule())); + return; + } + + String serviceName = event.getKey().substring(RouterConstant.ROUTER_KEY_PREFIX.length() + 1); + List list = JSONArray.parseArray(JSONObject.toJSONString(getRules(event, serviceName)), Rule.class); + RuleUtils.removeInvalidRules(kind, list, RouterConstant.DUBBO_CACHE_NAME.equals(cacheName), + RouterConstant.DUBBO_CACHE_NAME.equals(cacheName)); + if (CollectionUtils.isEmpty(list)) { + configuration.removeServiceRule(serviceName, kind); + } else { + list.sort((o1, o2) -> o2.getPrecedence() - o1.getPrecedence()); + configuration.updateServiceRule(serviceName, getEntireRule(kind, list)); + } + RuleUtils.initKeys(configuration); + RouterEventCollector.getInstance() + .collectServiceRouteRuleEvent(JSON.toJSONString(configuration.getRouteRule())); + } + + private EntireRule getEntireRule(String kind, List rules) { + EntireRule entireRule = new EntireRule(); + entireRule.setKind(kind); + entireRule.setRules(rules); + return entireRule; + } + + private List> getRules(DynamicConfigEvent event) { + String content = event.getContent(); + if (StringUtils.isBlank(content)) { + return Collections.emptyList(); + } + Map>> map = yaml.load(content); + return map.get(RouterConstant.GLOBAL_ROUTER_KEY); + } + + private List> getRules(DynamicConfigEvent event, String serviceName) { + String content = event.getContent(); + if (StringUtils.isBlank(content)) { + return Collections.emptyList(); + } + Map>> map = yaml.load(content); + return map.get(RouterConstant.ROUTER_KEY_PREFIX + RouterConstant.POINT + serviceName); + } + + private Map getRouteRuleMap(DynamicConfigEvent event) { + String content = event.getContent(); + Map routeRuleMap = yaml.load(content); + if (CollectionUtils.isEmpty(routeRuleMap)) { + return Collections.emptyMap(); + } + return routeRuleMap; + } +} diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandler.java new file mode 100644 index 0000000000..f626f6eb1f --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandler.java @@ -0,0 +1,54 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import java.util.HashSet; +import java.util.Set; + +/** + * 流量配置处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public class FlowKindHandler extends AbstractKindHandler { + private final Set keys; + + /** + * 构造方法 + */ + public FlowKindHandler() { + this.keys = new HashSet<>(); + this.keys.add(RouterConstant.GLOBAL_ROUTER_KEY); + this.keys.add(RouterConstant.ROUTER_KEY_PREFIX); + } + + @Override + public boolean shouldHandle(String key, String content) { + return super.shouldHandle(key, content) + && (keys.contains(key) || key.startsWith(RouterConstant.ROUTER_KEY_PREFIX + RouterConstant.POINT)); + } + + @Override + public String getKind() { + return RouterConstant.FLOW_MATCH_KIND; + } +} diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandler.java new file mode 100644 index 0000000000..ace3e95178 --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandler.java @@ -0,0 +1,54 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import java.util.HashSet; +import java.util.Set; + +/** + * 泳道配置处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public class LaneKindHandler extends AbstractKindHandler { + private final Set keys; + + /** + * 构造方法 + */ + public LaneKindHandler() { + this.keys = new HashSet<>(); + this.keys.add(RouterConstant.GLOBAL_LANE_KEY); + this.keys.add(RouterConstant.LANE_KEY_PREFIX); + } + + @Override + public boolean shouldHandle(String key, String content) { + return super.shouldHandle(key, content) + && (keys.contains(key) || key.startsWith(RouterConstant.LANE_KEY_PREFIX + RouterConstant.POINT)); + } + + @Override + public String getKind() { + return RouterConstant.LANE_MATCH_KIND; + } +} diff --git a/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandler.java b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandler.java new file mode 100644 index 0000000000..925db9cac0 --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/main/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandler.java @@ -0,0 +1,54 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import java.util.HashSet; +import java.util.Set; + +/** + * 标签配置处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public class TagKindHandler extends AbstractKindHandler { + private final Set keys; + + /** + * 构造方法 + */ + public TagKindHandler() { + this.keys = new HashSet<>(); + this.keys.add(RouterConstant.GLOBAL_TAG_KEY); + this.keys.add(RouterConstant.TAG_KEY_PREFIX); + } + + @Override + public boolean shouldHandle(String key, String content) { + return super.shouldHandle(key, content) + && (keys.contains(key) || key.startsWith(RouterConstant.TAG_KEY_PREFIX + RouterConstant.POINT)); + } + + @Override + public String getKind() { + return RouterConstant.TAG_MATCH_KIND; + } +} 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 f06eb4514a..7af50d4ff9 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 @@ -19,10 +19,13 @@ import com.huaweicloud.sermant.core.common.LoggerFactory; import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigEvent; import com.huaweicloud.sermant.core.service.dynamicconfig.common.DynamicConfigListener; -import com.huaweicloud.sermant.router.config.handler.AbstractConfigHandler; +import com.huaweicloud.sermant.router.config.handler.AbstractHandler; import com.huaweicloud.sermant.router.config.handler.GlobalConfigHandler; import com.huaweicloud.sermant.router.config.handler.RouterConfigHandler; import com.huaweicloud.sermant.router.config.handler.ServiceConfigHandler; +import com.huaweicloud.sermant.router.config.handler.kind.FlowKindHandler; +import com.huaweicloud.sermant.router.config.handler.kind.LaneKindHandler; +import com.huaweicloud.sermant.router.config.handler.kind.TagKindHandler; import java.util.HashSet; import java.util.Locale; @@ -40,7 +43,7 @@ public class RouterConfigListener implements DynamicConfigListener { private final String cacheName; - private final Set handlers; + private final Set handlers; /** * 构造方法 @@ -53,13 +56,16 @@ public RouterConfigListener(String cacheName) { this.handlers.add(new GlobalConfigHandler()); this.handlers.add(new RouterConfigHandler()); this.handlers.add(new ServiceConfigHandler()); + this.handlers.add(new FlowKindHandler()); + this.handlers.add(new LaneKindHandler()); + this.handlers.add(new TagKindHandler()); } @Override public void process(DynamicConfigEvent event) { String key = event.getKey(); handlers.forEach(handler -> { - if (handler.shouldHandle(key)) { + if (handler.shouldHandle(key, event.getContent())) { handler.handle(event, cacheName); } }); diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandlerTest.java index b41538133d..5d6cea5e1b 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandlerTest.java +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/GlobalConfigHandlerTest.java @@ -16,6 +16,8 @@ package com.huaweicloud.sermant.router.config.handler; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + import org.junit.Assert; import org.junit.Test; @@ -37,6 +39,6 @@ public GlobalConfigHandlerTest() { */ @Test public void testShouldHandle() { - Assert.assertTrue(handler.shouldHandle("servicecomb.globalRouteRule")); + Assert.assertTrue(handler.shouldHandle("servicecomb.globalRouteRule", RouterConstant.FLOW_MATCH_KIND)); } } diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandlerTest.java index e816b89278..fd611ed6e6 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandlerTest.java +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/RouterConfigHandlerTest.java @@ -16,6 +16,8 @@ package com.huaweicloud.sermant.router.config.handler; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + import org.junit.Assert; import org.junit.Test; @@ -37,7 +39,7 @@ public RouterConfigHandlerTest() { */ @Test public void testShouldHandle() { - Assert.assertTrue(handler.shouldHandle("servicecomb.routeRule")); - Assert.assertFalse(handler.shouldHandle("servicecomb.routeRule.foo")); + Assert.assertTrue(handler.shouldHandle("servicecomb.routeRule", RouterConstant.FLOW_MATCH_KIND)); + Assert.assertFalse(handler.shouldHandle("servicecomb.routeRule.foo", RouterConstant.FLOW_MATCH_KIND)); } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandlerTest.java index c31c6d94ed..c7616aca84 100644 --- a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandlerTest.java +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/ServiceConfigHandlerTest.java @@ -16,6 +16,8 @@ package com.huaweicloud.sermant.router.config.handler; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + import org.junit.Assert; import org.junit.Test; @@ -37,7 +39,7 @@ public ServiceConfigHandlerTest() { */ @Test public void testShouldHandle() { - Assert.assertTrue(handler.shouldHandle("servicecomb.routeRule.foo")); - Assert.assertFalse(handler.shouldHandle("servicecomb.routeRule")); + Assert.assertTrue(handler.shouldHandle("servicecomb.routeRule.foo", RouterConstant.FLOW_MATCH_KIND)); + Assert.assertFalse(handler.shouldHandle("servicecomb.routeRule", RouterConstant.FLOW_MATCH_KIND)); } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandlerTest.java new file mode 100644 index 0000000000..52c4c7f7ad --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/FlowKindHandlerTest.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 测试流量配置处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public class FlowKindHandlerTest { + private final AbstractKindHandler handler; + + public FlowKindHandlerTest() { + this.handler = new FlowKindHandler(); + } + + /** + * 测试shouldHandle方法 + */ + @Test + public void testShouldHandle() { + Assert.assertTrue(handler.shouldHandle(RouterConstant.GLOBAL_ROUTER_KEY, "")); + Assert.assertFalse(handler.shouldHandle(RouterConstant.GLOBAL_ROUTER_KEY, RouterConstant.FLOW_MATCH_KIND)); + } +} diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandlerTest.java new file mode 100644 index 0000000000..13cf61238f --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/LaneKindHandlerTest.java @@ -0,0 +1,47 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 测试泳道配置处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public class LaneKindHandlerTest { + private final AbstractKindHandler handler; + + public LaneKindHandlerTest() { + this.handler = new LaneKindHandler(); + } + + /** + * 测试shouldHandle方法 + */ + @Test + public void testShouldHandle() { + Assert.assertTrue(handler.shouldHandle(RouterConstant.LANE_KEY_PREFIX, "")); + Assert.assertFalse(handler.shouldHandle(RouterConstant.LANE_KEY_PREFIX, RouterConstant.LANE_MATCH_KIND)); + } +} diff --git a/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandlerTest.java b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandlerTest.java new file mode 100644 index 0000000000..4d7fc32bf6 --- /dev/null +++ b/sermant-plugins/sermant-router/router-config-service/src/test/java/com/huaweicloud/sermant/router/config/handler/kind/TagKindHandlerTest.java @@ -0,0 +1,48 @@ +/* + * + * * Copyright (C) 2024-2024 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.kind; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 测试标签配置处理器 + * + * @author provenceee + * @since 2024-01-11 + */ +public class TagKindHandlerTest { + private final AbstractKindHandler handler; + + public TagKindHandlerTest() { + this.handler = new TagKindHandler(); + } + + /** + * 测试shouldHandle方法 + */ + @Test + public void testShouldHandle() { + Assert.assertTrue(handler.shouldHandle(RouterConstant.TAG_KEY_PREFIX + ".foo", "")); + Assert.assertFalse( + handler.shouldHandle(RouterConstant.TAG_KEY_PREFIX + ".foo", RouterConstant.TAG_MATCH_KIND)); + } +}