關於zuul如何實現動態路由,已經有大神寫博客詳解過,這裏不囉嗦了,文章地址:Spring Cloud Zuul實現動態路由,我們就從這篇文章最後的一個問題講起,做者在最後實現動態刷新路由規則時說:爲何不本身是手動從新加載Locator.dorefresh?非要用事件去刷新?這牽扯到內部的zuul內部組件的工做流程,不單單是Locator自己的一個變量,具體想要了解的還得去看源碼。下面咱們就來分析下zuul的源碼看看爲何要這樣作?
要講清楚zuul的事件驅動模型,還得知道spring的事件驅動模型,由於zuul的實現正是利用了spring的事件驅動模型實現的。下面看看spring提供的事件模型圖:spring
在zuul中有這樣一個實現了ApplicationListener的監聽器ZuulRefreshListener ,代碼以下:app
private static class ZuulRefreshListener implements ApplicationListener<ApplicationEvent> { @Autowired private ZuulHandlerMapping zuulHandlerMapping; private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor(); @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent || event instanceof RefreshScopeRefreshedEvent || event instanceof RoutesRefreshedEvent) { this.zuulHandlerMapping.setDirty(true); } else if (event instanceof HeartbeatEvent) { if (this.heartbeatMonitor.update(((HeartbeatEvent) event).getValue())) { this.zuulHandlerMapping.setDirty(true); } } } }
由此可知在發生ContextRefreshedEvent和RoutesRefreshedEvent事件時會執行this.zuulHandlerMapping.setDirty(true);ide
public void setDirty(boolean dirty) { this.dirty = dirty; if (this.routeLocator instanceof RefreshableRouteLocator) { ((RefreshableRouteLocator) this.routeLocator).refresh(); } }
這樣在spring容器啓動完成後就刷新了路由規則。所以咱們若是要主動刷新路由規則,只須要發佈一個RoutesRefreshedEvent事件便可,代碼以下this
public void refreshRoute() { RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator); this.publisher.publishEvent(routesRefreshedEvent); logger.info("刷新了路由規則......"); }