二、DynamicZuulRouteLocator小优化
在之前的文章中提到,HeartbeatEvent
事件会频繁触发,每次都需要去查询数据库。而且ZuulRefreshListener
监听的其余四个刷新事件也不会经常触发。所以这里就可以做一下小优化,因为系统上线稳定后,路由一般是不会经常变动的。所以我们可以把路由规则配置给缓存起来,这样就不会每次的心跳都去查询数据库。
这里有分两种情况:
- 单机Zuul网关下的本地缓存
- Zuul网关集群下的分布式缓存
2.1 本地缓存
直接上代码:
public class DynamicZuulRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
private final ZuulProperties zuulProperties;
private final RoutingRuleService routingRuleService;
private static final ConcurrentHashMap<String, ZuulRoute> routesCache = new ConcurrentHashMap<>();
public DynamicZuulRouteLocator(String servletPath, ZuulProperties properties, RoutingRuleService routingRuleService) {
super(servletPath, properties);
this.zuulProperties = properties;
this.routingRuleService = routingRuleService;
}
@Override
public void refresh() {
doRefresh();
}
@Override
protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
Map<String, ZuulProperties.ZuulRoute> allRoutes = null;
if (routesCache.isEmpty()) {
allRoutes = routingRuleService.findAllRoutes();
routesCache.putAll(allRoutes);
} else {
allRoutes = routesCache;
}
LinkedHashMap<String, ZuulProperties.ZuulRoute> routesMap = new LinkedHashMap<>();
// 父类的 SimpleRouteLocator的locateRoutes()读取的是配置文件中的路由规则配置
routesMap.putAll(super.locateRoutes());
routesMap.putAll(allRoutes);
LinkedHashMap<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>();
routesMap.forEach((key, value) -> {
String path = key;
if (!path.startsWith("/")) {
path = "/" + path;
}
if (StringUtils.hasText(this.zuulProperties.getPrefix())) {
path = this.zuulProperties.getPrefix() + path;
if (!path.startsWith("/")) {
path = "/" + path;
}
}
values.put(path, value);
});
return values;
}
public static void clearCache() {
routesCache.clear();
}
}
复制代码
这是简单地使用了ConcurrentHashMap
作为本地缓存。当然也可以使用caffeine
、Guava Cache
、Ehcache
等本地缓存框架。使用ConcurrentHashMap
主要