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。

@PostConstructpublic 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工夫,达到动静路由的目标。