1、概述
zuul是基于spring mvc实现的。过滤器有
其中标黑的过滤器在使用@EnableZuulProxy才开始,其他在@EnableZuulProxy和EnableZuulServer开启
2、接口设计
2.1 Filter
在ZuulHandlerMapping中注册了ZuulController,其中ZuulController处理是通过ZuulServlet来处理的,在启动时会通过FilterRegistry来加载ZuulFilter.
2.2 路由
主要是Route和RouteLocator,其结构为
RouteLocator:根据请求url得到Route
RefreshableRouteLocator:支持更新路由
SimpleRouteLocator:RouteLocator的实现类
CompoisteRouteLocator:RefreshableRouteLocator的实现类,内部包括RouteLocator的列表,使用了组合模式
2.3 动态路由
动态路由与ZuulRefreshListener相关,其是spring事件类型的监听器。
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
|| 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());
}
}
private void resetIfNeeded(Object value) {
if (this.heartbeatMonitor.update(value)) {
reset();
}
}
private void reset() {
this.zuulHandlerMapping.setDirty(true);
}
}
其支持的事件类型有
- ContextRefreshedEvent
- RefreshScopeRefreshedEvent
- RouteRefreshedEvent
- InstanceRegisteredEvent
- ParentHeartbeatEvent
- HeartbeatEvent
事件发生时,会将ZuulHandlerMapping的dirty标识设置为true。ZuulHandlerMapping在根据url及请求查找对应的Handler时,会判断dirty标识,如果为true,会通过RouteLocator获取所有路由重新注册到Mapping中。
protected Object lookupHandler(String urlPath, HttpServletRequest request)
throws Exception {
if (this.errorController != null
&& urlPath.equals(this.errorController.getErrorPath())) {
return null;
}
if (isIgnoredPath(urlPath, this.routeLocator.getIgnoredPaths())) {
return null;
}
RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.containsKey("forward.to")) {
return null;
}
if (this.dirty) {
synchronized (this) {
if (this.dirty) {
registerHandlers();
this.dirty = false;
}
}
}
return super.lookupHandler(urlPath, request);
}
private void registerHandlers() {
Collection<Route> routes = this.routeLocator.getRoutes();
if (routes.isEmpty()) {
this.logger.warn("No routes found from RouteLocator");
}
else {
for (Route route : routes) {
registerHandler(route.getFullPath(), this.zuul);
}
}
}
参考资料: