(记)路由匹配优化方案测试
偶然听到xxx同事接到一个网关性能优化任务【路由匹配优化】,正好在复习数据结构这块的知识,于是研究了下,如果是我,我怎么做这块的优化?
思考
既然是网关性能优化,无疑是为了提高网关性能,在网关进行请求代理的时候,就需要经过路由匹配,然后下一步请求。
那么能否通过降低路由匹配的耗时来提高网关的处理性能?
于是分析路由匹配的耗时主要在哪里。以下为目前路由匹配的简化代码:
// 这里用了spring的matcher来进行路径匹配
private AntPathMatcher matcher = new AntPathMatcher();
public Route match(String path) {
for (String route : routes) {
if (matcher.match(route, path)) {
return new Route(route);
}
}
return null;
}
可以看到耗时可能在于循环的matcher.match(),一个是循环次数,二个是matcher字符串匹配速度。
从这里有了两个思路,一是降低平均循环次数,二是优化matcher字符串匹配的速度。
matcher在字符串匹配的速度已经非常快了,优化空间非常小,所以考虑如何降低平均循环次数,也就是降低时间复杂度。
既然是降低时间复杂度,就得考虑通过设计新的数据结构来提高路由匹配速度。
联想到mysql的索引,当mysql中一张表的数据过多时,且没有索引的情况下,一次查询会扫描全表,而路由匹配的场景也与之非常相似,路由匹配也是通过扫描来筛选符合条件的数据。
那么,从构建索引的思路上考虑,路由匹配能基于什么做索引呢?
/schema-1/service-route-1/v1/a
/schema-1/service-route-1/v2/a
/schema-2/service-route-2/v1/c
/schema-3/service-route-3/**
/schema-4/**
假设一个/schema-1/service-route-1/xxx请求进入,如果我能直接筛选掉一部分路由就可以减少遍历次数,可以发现,如果把路由根据path的层级来构建树,那么就可以直接通过每个层级来筛选掉无用数据,并且筛选率非常高。前缀树就非常适合这个场景!
前缀树方案
用于测试的前缀树代码:
public class TreeRouteMatcher implements RouteMatcher {
private static final String GENERAL_PATTERN = "**";
private TreeNode tree = new TreeNode("");
@Override
public void setRoutes(List<Route>