This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit efcc78a4b45076c9a3f19b983beb120f34b76df3 Author: GuoYL <[email protected]> AuthorDate: Wed Nov 20 18:15:21 2019 +0800 [SCB-1407] fix bug and improve code --- handlers/handler-router/pom.xml | 14 ---- .../apache/servicecomb/router/RouterFilter.java | 7 +- .../servicecomb/router/cache/RouterRuleCache.java | 87 ++++++++++------------ .../router/constom/CanaryInvokeFilter.java | 23 +++--- .../router/constom/CanaryServerListFilter.java | 19 +++-- .../distribute/AbstractRouterDistributor.java | 20 +++-- .../router/match/RouterRuleMatcher.java | 2 +- .../servicecomb/router/model/HeaderRule.java | 9 ++- .../apache/servicecomb/router/model/Matcher.java | 14 +--- .../servicecomb/router/model/PolicyRuleItem.java | 4 +- .../apache/servicecomb/router/model/RouteItem.java | 6 +- .../servicecomb/router/model/ServiceInfoCache.java | 5 +- .../apache/servicecomb/router/model/TagItem.java | 13 +--- .../router/util/VersionCompareUtil.java | 2 +- 14 files changed, 100 insertions(+), 125 deletions(-) diff --git a/handlers/handler-router/pom.xml b/handlers/handler-router/pom.xml index 0bb62e5..f5b02d1 100644 --- a/handlers/handler-router/pom.xml +++ b/handlers/handler-router/pom.xml @@ -30,24 +30,10 @@ <dependencies> <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> -<!-- <scope>test</scope>--> - </dependency> - <dependency> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> -<!-- <scope>test</scope>--> - </dependency> - <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon-loadbalancer</artifactId> </dependency> <dependency> - <groupId>com.netflix.hystrix</groupId> - <artifactId>hystrix-core</artifactId> - </dependency> - <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java index 9cbd49f..c2397e4 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/RouterFilter.java @@ -49,16 +49,15 @@ public class RouterFilter { if (headers == null) { headers = new HashMap<>(); } - LOGGER.debug("route management headers:{}", headers); /** - * 1.初始化--进行cache缓存 + * 1.init and cache */ if (!RouterRuleCache.doInit(targetServiceName)) { LOGGER.debug("route management init failed"); return list; } /** - * 2.match--拿到invoke相关信息 (header),匹配到唯一的rule + * 2.match rule */ PolicyRuleItem invokeRule = RouterRuleMatcher.getInstance().match(targetServiceName, headers); @@ -70,7 +69,7 @@ public class RouterFilter { LOGGER.debug("route management match rule success: {}", invokeRule); /** - * 3.distribute--拿到server list选择endpoint进行流量分配 + * 3.distribute select endpoint */ List<T> resultList = distributer.distribute(targetServiceName, list, invokeRule); diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java index ec438a5..5698357 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java @@ -45,65 +45,58 @@ public class RouterRuleCache { private static Interner<String> servicePool = Interners.newWeakInterner(); /** - * 每次序列化额外缓存,配置更新时触发回调函数 返回false即初始化规则失败: 1. 规则解析错误 2. 规则为空 + * cache and register callback return false when: 1. parsing error 2. rule is null * * @param targetServiceName * @return */ public static boolean doInit(String targetServiceName) { - if (serviceInfoCacheMap.containsKey(targetServiceName)) { - return true; - } - //这里使用guava包装String.intern():因为String.intern()分配在Old Generation,容易引发fullgc - synchronized (servicePool.intern(targetServiceName)) { - //Yaml not thread-safe - Yaml yaml = new Yaml(); - DynamicStringProperty ruleStr = DynamicPropertyFactory.getInstance().getStringProperty( - String.format(ROUTE_RULE, targetServiceName), null, () -> { - refresh(targetServiceName); - DynamicStringProperty tepRuleStr = DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(ROUTE_RULE, targetServiceName), null); - if (tepRuleStr.get() == null) { - return; - } - try { - List<PolicyRuleItem> temList = Arrays - .asList(yaml.loadAs(tepRuleStr.get(), PolicyRuleItem[].class)); - RouterRuleCache.addAllRule(targetServiceName, temList); - } catch (Exception e) { - LOGGER.error("route management Serialization failed {}", e.getMessage()); - return; - } - }); - if (ruleStr.get() == null) { - return false; - } - try { - addAllRule(targetServiceName, - Arrays.asList(yaml.loadAs(ruleStr.get(), PolicyRuleItem[].class))); - } catch (Exception e) { - LOGGER.error("route management Serialization failed: {}", e.getMessage()); - return false; + if (!serviceInfoCacheMap.containsKey(targetServiceName)) { + synchronized (servicePool.intern(targetServiceName)) { + if (!serviceInfoCacheMap.containsKey(targetServiceName)) { + return true; + } + //Yaml not thread-safe + Yaml yaml = new Yaml(); + DynamicStringProperty ruleStr = DynamicPropertyFactory.getInstance().getStringProperty( + String.format(ROUTE_RULE, targetServiceName), null, () -> { + refresh(targetServiceName); + DynamicStringProperty tepRuleStr = DynamicPropertyFactory.getInstance() + .getStringProperty(String.format(ROUTE_RULE, targetServiceName), null); + addAllRule(targetServiceName, yaml, tepRuleStr); + }); + return addAllRule(targetServiceName, yaml, ruleStr); } - return true; } + return true; } - private static void addAllRule(String targetServiceName, - List<PolicyRuleItem> policyRuleItemList) { + private static boolean addAllRule(String targetServiceName, Yaml yaml, + DynamicStringProperty ruleStr) { + if (ruleStr.get() == null) { + return false; + } + List<PolicyRuleItem> policyRuleItemList = Arrays + .asList(yaml.loadAs(ruleStr.get(), PolicyRuleItem[].class)); if (CollectionUtils.isEmpty(policyRuleItemList)) { - return; + return false; } - if (serviceInfoCacheMap.get(targetServiceName) == null) { - serviceInfoCacheMap.put(targetServiceName, new ServiceInfoCache()); + try { + if (serviceInfoCacheMap.get(targetServiceName) == null) { + serviceInfoCacheMap.put(targetServiceName, new ServiceInfoCache()); + } + serviceInfoCacheMap.get(targetServiceName).setAllrule(policyRuleItemList); + // init tagitem + serviceInfoCacheMap.get(targetServiceName).getAllrule().forEach(a -> + a.getRoute().forEach(b -> b.initTagItem()) + ); + // sort by precedence + serviceInfoCacheMap.get(targetServiceName).sortRule(); + } catch (Exception e) { + LOGGER.error("route management Serialization failed: {}", e.getMessage()); + return false; } - serviceInfoCacheMap.get(targetServiceName).setAllrule(policyRuleItemList); - // 这里初始化tagitem - serviceInfoCacheMap.get(targetServiceName).getAllrule().forEach(a -> - a.getRoute().forEach(b -> b.initTagItem()) - ); - // 按照优先级排序 - serviceInfoCacheMap.get(targetServiceName).sortRule(); + return true; } public static ConcurrentHashMap<String, ServiceInfoCache> getServiceInfoCacheMap() { diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryInvokeFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryInvokeFilter.java index c1e8a02..d130b1f 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryInvokeFilter.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryInvokeFilter.java @@ -39,13 +39,13 @@ import org.yaml.snakeyaml.Yaml; import com.netflix.config.DynamicPropertyFactory; -import io.vertx.core.json.Json; - public class CanaryInvokeFilter implements HttpServerFilter { private static final Logger LOGGER = LoggerFactory.getLogger(CanaryInvokeFilter.class); - private static final String PASS_HEADER = "servicecomb.router.header"; + private static final String SERVICECOMB_ROUTER_HEADER = "servicecomb.router.header"; + + private static final String ROUTER_HEADER = "X-RouterContext"; private static List<String> allHeader = new ArrayList<>(); @@ -65,7 +65,7 @@ public class CanaryInvokeFilter implements HttpServerFilter { } /** - * 透传Header需要在这里实现, 因为无法预知调用链上的服务匹配所需要header, 提供两种模式 1.取到全量的header并放到context中, 2.从配置中解析并读取 + * pass through headers * * @param invocation * @param httpServletRequestEx @@ -75,32 +75,31 @@ public class CanaryInvokeFilter implements HttpServerFilter { public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx httpServletRequestEx) { loadHeaders(); - if (invocation.getContext("canary_context") != null && !CollectionUtils.isEmpty(allHeader)) { + if (invocation.getContext(ROUTER_HEADER) != null && !CollectionUtils.isEmpty(allHeader)) { Map<String, String> headerMap = getHeaderMap(httpServletRequestEx); try { - invocation.addContext("canary_context", JsonUtils.OBJ_MAPPER.writeValueAsString(headerMap)); + invocation.addContext(ROUTER_HEADER, JsonUtils.OBJ_MAPPER.writeValueAsString(headerMap)); } catch (JsonProcessingException e) { LOGGER.error("canary context serialization failed"); - e.printStackTrace(); } } return null; } /** - * 读配置文件Header + * read config and get Header */ private void loadHeaders() { DynamicStringProperty headerStr = DynamicPropertyFactory.getInstance() - .getStringProperty(PASS_HEADER, null, () -> { + .getStringProperty(SERVICECOMB_ROUTER_HEADER, null, () -> { allHeader = null; DynamicStringProperty temHeader = DynamicPropertyFactory.getInstance() - .getStringProperty(PASS_HEADER, null); + .getStringProperty(SERVICECOMB_ROUTER_HEADER, null); Yaml yaml = new Yaml(); allHeader = yaml.load(temHeader.get()); }); try { - if (allHeader != null) { + if (!CollectionUtils.isEmpty(allHeader)) { Yaml yaml = new Yaml(); allHeader = yaml.load(headerStr.get()); } @@ -110,7 +109,7 @@ public class CanaryInvokeFilter implements HttpServerFilter { } /** - * 取出所用的header + * get header from request * * @param httpServletRequestEx * @return diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryServerListFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryServerListFilter.java index 4397ffc..0c8307a 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryServerListFilter.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/constom/CanaryServerListFilter.java @@ -28,21 +28,28 @@ import org.apache.servicecomb.loadbalance.ServerListFilterExt; import org.apache.servicecomb.loadbalance.ServiceCombServer; import com.netflix.config.DynamicPropertyFactory; -import io.vertx.core.json.Json; import org.apache.servicecomb.router.RouterFilter; import org.apache.servicecomb.router.distribute.RouterDistributor; import org.apache.servicecomb.serviceregistry.api.registry.Microservice; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CanaryServerListFilter implements ServerListFilterExt { - private static final String ENABLE = "servicecomb.release_way"; + private static final Logger LOGGER = LoggerFactory.getLogger(CanaryServerListFilter.class); + + private static final String ENABLE = "servicecomb.router.type"; + + private static final String TYPE_ROUTER = "router"; + + private static final String ROUTER_HEADER = "X-RouterContext"; RouterDistributor<ServiceCombServer, Microservice> distributer = new ServiceCombCanaryDistributer(); @Override public boolean enabled() { return DynamicPropertyFactory.getInstance().getStringProperty(ENABLE, "").get() - .equals("canary"); + .equals("TYPE_ROUTER"); } @Override @@ -57,15 +64,15 @@ public class CanaryServerListFilter implements ServerListFilterExt { private Map<String, String> addHeaders(Invocation invocation) { Map<String, String> headers = new HashMap<>(); - if (invocation.getContext("canary_context") != null) { + if (invocation.getContext(ROUTER_HEADER) != null) { Map<String, String> canaryContext = null; try { canaryContext = JsonUtils.OBJ_MAPPER - .readValue(invocation.getContext("canary_context"), + .readValue(invocation.getContext(ROUTER_HEADER), new TypeReference<Map<String, String>>() { }); } catch (JsonProcessingException e) { - e.printStackTrace(); + LOGGER.error("canary context serialization failed"); } if (canaryContext != null) { headers.putAll(canaryContext); diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java index 83e1cc9..646374c 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java @@ -51,22 +51,20 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements @Override public List<T> distribute(String targetServiceName, List<T> list, PolicyRuleItem invokeRule) { - //初始化LatestVersion + //init LatestVersion initLatestVersion(targetServiceName, list); invokeRule.check( RouterRuleCache.getServiceInfoCacheMap().get(targetServiceName).getLatestVersionTag()); - // 建立tag list + // get tag list Map<TagItem, List<T>> versionServerMap = getDistributList(targetServiceName, list, invokeRule); - //如果没有匹配到合适的规则,直接返回最新版本的服务列表 if (CollectionUtils.isEmpty(versionServerMap)) { LOGGER.debug("route management can not match any rule and route the latest version"); return getLatestVersionList(list, targetServiceName); } - // 分配流量,返回结果 TagItem targetTag = getFiltedServerTagItem(invokeRule, targetServiceName); if (versionServerMap.containsKey(targetTag)) { return versionServerMap.get(targetTag); @@ -91,8 +89,11 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements } /** - * 1.过滤targetService 2.返回按照version和tags分配list 这里之所以需要建立Map,而不是直接遍历List来分配是因为需要考虑 “多重匹配” - * 因为getProperties中除了tag还有其他的无关字段 + * 1.filter targetService + * 2.return map distributed by version and tags + * establish map is a more complicate way than direct traversal, + * because we need to consider multiple matches, + * getProperties contains other irrelevant field except tags. * * @param serviceName * @param list @@ -159,7 +160,12 @@ public abstract class AbstractRouterDistributor<T extends Server, E> implements RouterRuleCache.getServiceInfoCacheMap().get(serviceName).setLatestVersionTag(tagitem); } - + /** + * + * @param list + * @param targetServiceName + * @return + */ public List<T> getLatestVersionList(List<T> list, String targetServiceName) { String latestV = RouterRuleCache.getServiceInfoCacheMap().get(targetServiceName) .getLatestVersionTag().getVersion(); diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java index 5133eb0..7e3303e 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java @@ -36,7 +36,7 @@ public class RouterRuleMatcher { } /** - * 匹配到合适的rule 匹配规则即: source (目标服务名字) sourceTags (一期先不考虑) headers (匹配header字段) + * only match header * * @param serviceName * @return diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java index 332b9f2..077baf7 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java @@ -28,11 +28,14 @@ public class HeaderRule { private static final Logger LOGGER = LoggerFactory.getLogger(HeaderRule.class); - //正则 private String regex; - //是否区分大小写 false区分 true不区分 + + /** + * false distinct + * true Ignore + */ private Boolean caseInsensitive = false; - //精准匹配 + private String exact; public HeaderRule() { diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/Matcher.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/Matcher.java index 83f5b66..3f3819e 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/Matcher.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/Matcher.java @@ -24,25 +24,17 @@ import java.util.Map; **/ public class Matcher { - //服务级别 private String source; - //服务级别 -- 这个暂时不考虑 + private Map<String, String> sourceTags; - //invoke级别 + private Map<String, HeaderRule> headers; - //这个暂时不考虑 + private String refer; public Matcher() { } - public boolean filte(String sourcName, Map<String, String> sourceTags) { - if (sourcName != null && !sourcName.equals(source)) { - return false; - } - return true; - } - public boolean match(Map<String, String> realHeaders) { if (headers == null) { return true; diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java index aee0c9a..4d6daaa 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java @@ -34,7 +34,7 @@ public class PolicyRuleItem implements Comparable<PolicyRuleItem> { private Matcher match; - // any match 只要version符合就算符合匹配规则 + // any match private List<RouteItem> route; private Integer total; @@ -45,7 +45,7 @@ public class PolicyRuleItem implements Comparable<PolicyRuleItem> { } /** - * 如果weight和小于100,用latestVersion补充 + * if weight is less than 100, fill with minimum version * * @param latestVersionTag */ diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/RouteItem.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/RouteItem.java index 6afa2b3..acabbff 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/RouteItem.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/RouteItem.java @@ -26,12 +26,10 @@ public class RouteItem implements Comparable<RouteItem> { private Integer weight; /** - * 负载均衡参数 + * for load balance */ private Integer currentWeight = 0; - /** - * 为了提高序列化速度设置为Map 固定字段 version - */ + private Map<String, String> tags; private TagItem tagitem; diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java index 903ef45..5a49261 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java @@ -26,7 +26,10 @@ import java.util.stream.Collectors; public class ServiceInfoCache { private List<PolicyRuleItem> allrule; - //用于default的情况 + + /** + * for default version + */ private TagItem latestVersionTag; public ServiceInfoCache() { diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/TagItem.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/TagItem.java index 3f3230a..44d18c3 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/TagItem.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/model/TagItem.java @@ -67,11 +67,6 @@ public class TagItem { this.param = param; } - /** - * map在匹配key调用 - * - * @return - */ @Override public int hashCode() { int result = Objects.hash(version); @@ -81,12 +76,6 @@ public class TagItem { return result; } - /** - * all match map在匹配key调用 - * - * @param obj - * @return - */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -110,7 +99,7 @@ public class TagItem { /** - * 返回匹配的个数 + * return match num * * @param item * @return diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java index 7b17d8e..9d92917 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/util/VersionCompareUtil.java @@ -22,7 +22,7 @@ package org.apache.servicecomb.router.util; **/ public class VersionCompareUtil { /** - * 前者大则返回一个正数 + * if first num is bigger then return a positive number * * @param version1 * @param version2
