共计 3258 个字符,预计需要花费 9 分钟才能阅读完成。
Zuul- 启动,咱们提到了 zuulRefreshRoutesListener,能够用来动静刷新路由,咱们看看他是怎么加载的。
一下这几个事件会触发 reset 办法。
public void onApplicationEvent(ApplicationEvent event) { | |
if (event instanceof ContextRefreshedEvent | |
|| event instanceof RefreshScopeRefreshedEvent | |
|| event instanceof RoutesRefreshedEvent | |
|| event instanceof InstanceRegisteredEvent) {reset(); | |
} | |
else if (event instanceof ParentHeartbeatEvent) {ParentHeartbeatEvent e = (ParentHeartbeatEvent) event; | |
resetIfNeeded(e.getValue()); | |
} | |
else if (event instanceof HeartbeatEvent) {HeartbeatEvent e = (HeartbeatEvent) event; | |
resetIfNeeded(e.getValue()); | |
} | |
} |
DiscoveryClientRouteLocator#locateRoutes
追着这个办法上来,咱们最初会到 DiscoveryClientRouteLocator#locateRoutes 办法。这里次要是获取两个中央的配置,一个是咱们的配置文件,一个是 Eureka 的注册表信息。
protected LinkedHashMap<String, ZuulRoute> locateRoutes() {LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>(); | |
// 先调用父类的办法,routesMap.putAll(super.locateRoutes()); | |
if (this.discovery != null) {Map<String, ZuulRoute> staticServices = new LinkedHashMap<>(); | |
for (ZuulRoute route : routesMap.values()) {String serviceId = route.getServiceId(); | |
if (serviceId == null) {serviceId = route.getId(); | |
} | |
if (serviceId != null) {staticServices.put(serviceId, route); | |
} | |
} | |
// 从 Eureka 获取注册表信息 | |
List<String> services = this.discovery.getServices(); | |
// 是否有过滤的条件 | |
String[] ignored = this.properties.getIgnoredServices() | |
.toArray(new String[0]); | |
for (String serviceId : services) {String key = "/" + mapRouteToService(serviceId) + "/**"; | |
if (staticServices.containsKey(serviceId) | |
&& staticServices.get(serviceId).getUrl() == null) {ZuulRoute staticRoute = staticServices.get(serviceId); | |
if (!StringUtils.hasText(staticRoute.getLocation())) {staticRoute.setLocation(serviceId); | |
} | |
} | |
if (!PatternMatchUtils.simpleMatch(ignored, serviceId) | |
&& !routesMap.containsKey(key)) {routesMap.put(key, new ZuulRoute(key, serviceId)); | |
} | |
} | |
} | |
if (routesMap.get(DEFAULT_ROUTE) != null) {ZuulRoute defaultRoute = routesMap.get(DEFAULT_ROUTE); | |
routesMap.remove(DEFAULT_ROUTE); | |
routesMap.put(DEFAULT_ROUTE, defaultRoute); | |
} | |
// 返回本地配置 +Eureka 未过滤的注册表 | |
LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>(); | |
for (Entry<String, ZuulRoute> entry : routesMap.entrySet()) {String path = entry.getKey(); | |
// Prepend with slash if not already present. | |
if (!path.startsWith("/")) {path = "/" + path;} | |
if (StringUtils.hasText(this.properties.getPrefix())) {path = this.properties.getPrefix() + path; | |
if (!path.startsWith("/")) {path = "/" + path;} | |
} | |
values.put(path, entry.getValue()); | |
} | |
return values; | |
} |
Eureka 的注册表有个 IgnoredServices 配置,咱们能够对他进行过滤,这样防止服务名称间接裸露进去。
zuul: | |
ignoredServices: '*' | |
routes: | |
users: /myusers/** |
SimpleRouteLocator#locateRoutes
读取本地的时候,间接从 ZuulProperties 取值。
protected Map<String, ZuulRoute> locateRoutes() {LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>(); | |
for (ZuulRoute route : this.properties.getRoutes().values()) {routesMap.put(route.getPath(), route); | |
} | |
return routesMap; | |
} |
ZuulProperties 被加载的时候,因为有一个 @PostConstruct
注解,他会调用 init 办法。在这里会依据咱们的配置信息进行赋值 serviceId、id、path。
@PostConstruct | |
public void init() {for (Entry<String, ZuulRoute> entry : this.routes.entrySet()) {ZuulRoute value = entry.getValue(); | |
if (!StringUtils.hasText(value.getLocation())) {value.serviceId = entry.getKey(); | |
} | |
if (!StringUtils.hasText(value.getId())) {value.id = entry.getKey(); | |
} | |
if (!StringUtils.hasText(value.getPath())) {value.path = "/" + entry.getKey() + "/**"; | |
} | |
} | |
} |
流程图
动静路由
咱们晓得了什么时候触发路由的从新加载,那咱们能够在路由信息扭转的时候,就调用触发他的条件,比方 RoutesRefreshedEvent。
咱们晓得了他的加载流程,先本地再注册核心,咱们也能够自定义本人的加载流程,比方先本地,再数据库,数据库变更,就触发 RoutesRefreshedEvent 工夫,达到动静路由的目标。
正文完