Zuul 架構圖
Zuul的官方文檔中的架構圖
從架構圖中可以看到 Zuul 通過Zuul Servlet 和 一系列 Zuul Filter 來完成智能路由和過濾器的功能。
Zuul 工作原理概述(轉)
在Zuul中,整個請求的過程是這樣的,首先將請求給 ZuulServlet 處理,ZuulServlet中有一個ZuulRunner對象,該對象中初始化了RequestContext, RequestContext 作為整個請求的上下文,封裝了請求的一些數據,並被所有的ZuulFilter共享。ZuulRunner 中還有 FilterProcessor ,FilterProcessor作為執行所有的ZuulFilter的管理器。FilterProcessor從 FilterLoader 中獲取ZuulFilter,而ZuulFilter是被FilterFileManager所加載,並支持groovy熱加載,採用了輪詢的方式熱加載。
有了這些Filter之後,ZuulServlet首先執行的pre類型的過濾器,再執行route類型的過濾器,最後執行的是post 類型的過濾器。
如果在執行這些過濾器有錯誤的時候則會執行error類型的過濾器。執行完這些過濾器,最終將請求的結果返回給客戶端。
Zuul 啟動—源碼分析
在程序的啟動類上加@EnableZuulProxy 註解,我們可以使用Zuul 提供的功能了,該註解的源碼為:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({ZuulProxyMarkerConfiguration.class})
public @interface EnableZuulProxy {
}
源碼中,@EnableZuulProxy 引入了ZuulProxyMarkerConfiguration 配置類,跟蹤ZuulProxyMarkerConfiguration 類:
public class ZuulProxyMarkerConfiguration {
public ZuulProxyMarkerConfiguration() {
}
@Bean
public ZuulProxyMarkerConfiguration.Marker zuulProxyMarkerBean() {
return new ZuulProxyMarkerConfiguration.Marker();
}
class Marker {
Marker() {
}
}
}
在ZuulProxyMarkerConfiguration 配置類中,發現只是註冊了一個ZuulProxyMarkerConfiguration.Marker的bean。我們通過分析應該會有依賴這個bean的配置類。然後我們找到了 ZuulProxyAutoConfiguration 依賴了ZuulProxyMarkerConfiguration.Marker的bean。
跟蹤 ZuulProxyAutoConfiguration :
@Configuration
@Import({RestClientRibbonConfiguration.class, OkHttpRibbonConfiguration.class, HttpClientRibbonConfiguration.class, HttpClientConfiguration.class})
@ConditionalOnBean({Marker.class})
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
@Bean
@ConditionalOnMissingBean({DiscoveryClientRouteLocator.class})
public DiscoveryClientRouteLocator discoveryRouteLocator() {
return new DiscoveryClientRouteLocator(this.server.getServlet().getContextPath(), this.discovery, this.zuulProperties, this.serviceRouteMapper, this.registration);
}
@Bean
@ConditionalOnMissingBean({PreDecorationFilter.class})
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) {
return new PreDecorationFilter(routeLocator, this.server.getServlet().getContextPath(), this.zuulProperties, proxyRequestHelper);
}
@Bean
@ConditionalOnMissingBean({RibbonRoutingFilter.class})
public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper, RibbonCommandFactory<?> ribbonCommandFactory) {
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers);
return filter;
}
@Bean
@ConditionalOnMissingBean({SimpleHostRoutingFilter.class, CloseableHttpClient.class})
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties, ApacheHttpClientConnectionManagerFactory connectionManagerFactory, ApacheHttpClientFactory httpClientFactory) {
return new SimpleHostRoutingFilter(helper, zuulProperties, connectionManagerFactory, httpClientFactory);
}
@Bean
@ConditionalOnMissingBean({SimpleHostRoutingFilter.class})
public SimpleHostRoutingFilter simpleHostRoutingFilter2(ProxyRequestHelper helper, ZuulProperties zuulProperties, CloseableHttpClient httpClient) {
return new SimpleHostRoutingFilter(helper, zuulProperties, httpClient);
}
@Bean
@ConditionalOnMissingBean({ServiceRouteMapper.class})
public ServiceRouteMapper serviceRouteMapper() {
return new SimpleServiceRouteMapper();
}
}
我們發現在類ZuulProxyAutoConfiguration中,引入了RestClientRibbonConfiguration, OkHttpRibbonConfiguration, HttpClientRibbonConfiguration, HttpClientConfiguration,Zuul默認是用HttpClientRibbonConfiguration做負載均衡配置, 注入了DiscoveryClient、RibbonConfiguration用作負載均衡相關。注入了一些列的Filter,pre類型: PreDecorationFilter ; // 裝飾 Requestroute類型: RibbonRoutingFilter , SimpleHostRoutingFilter ; // 路由Filter
在ZuulProxyAutoConfiguration 的父類ZuulServerAutoConfiguration中,也引入了一些配置信息:
@EnableConfigurationProperties({ZuulProperties.class})
@ConditionalOnClass({ZuulServlet.class, ZuulServletFilter.class})
@ConditionalOnBean({Marker.class})
public class ZuulServerAutoConfiguration {
// 在缺失`ZuulServlet`的情況下注入`ZuulServlet`
@Bean
@ConditionalOnMissingBean(
name = {"zuulServlet"}
)
@ConditionalOnProperty(
name = {"zuul.use-filter"},
havingValue = "false",
matchIfMissing = true
)
public ServletRegistrationBean zuulServlet() {
ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean(new ZuulServlet(), new String[]{this.zuulProperties.getServletPattern()});
servlet.addInitParameter("buffer-requests", "false");
return servlet;
}
// 在缺失`ZuulServletFilter`的情況下注入`ZuulServletFilter`
@Bean
@ConditionalOnMissingBean(
name = {"zuulServletFilter"}
)
@ConditionalOnProperty(
name = {"zuul.use-filter"},
havingValue = "true",
matchIfMissing = false
)
public FilterRegistrationBean zuulServletFilter() {
FilterRegistrationBean<ZuulServletFilter> filterRegistration = new FilterRegistrationBean();
filterRegistration.setUrlPatterns(Collections.singleton(this.zuulProperties.getServletPattern()));
filterRegistration.setFilter(new ZuulServletFilter());
filterRegistration.setOrder(2147483647);
filterRegistration.addInitParameter("buffer-requests", "false");
return filterRegistration;
}
// 注入 `ServletDetectionFilter`
@Bean
public ServletDetectionFilter servletDetectionFilter() {
return new ServletDetectionFilter();
}
// 注入 `FormBodyWrapperFilter`
@Bean
public FormBodyWrapperFilter formBodyWrapperFilter() {
return new FormBodyWrapperFilter();
}
// 注入 `DebugFilter`
@Bean
public DebugFilter debugFilter() {
return new DebugFilter();
}
// 注入 `Servlet30WrapperFilter`
@Bean
public Servlet30WrapperFilter servlet30WrapperFilter() {
return new Servlet30WrapperFilter();
}
// 注入 `SendResponseFilter`
@Bean
public SendResponseFilter sendResponseFilter(ZuulProperties properties) {
return new SendResponseFilter(this.zuulProperties);
}
// 注入 `SendErrorFilter`
@Bean
public SendErrorFilter sendErrorFilter() {
return new SendErrorFilter();
}
// 注入 `SendForwardFilter`
@Bean
public SendForwardFilter sendForwardFilter() {
return new SendForwardFilter();
}
@Configuration
protected static class ZuulFilterConfiguration {
@Autowired
private Map<String, ZuulFilter> filters;
protected ZuulFilterConfiguration() {
}
// ZuulFilterInitializer,在初始化類中將Filter向FilterRegistry註冊
@Bean
public ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory, TracerFactory tracerFactory) {
FilterLoader filterLoader = FilterLoader.getInstance();
FilterRegistry filterRegistry = FilterRegistry.instance();
return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry);
}
}
}
父類ZuulServerAutoConfiguration中,在缺失ZuulServlet ,ZuulServletFilter的bean的情況下,注入ZuulServlet ,ZuulServletFilter。同時也注入了其他的過濾器,pre類型: ServletDetectionFilter,DebugFilter ,Servlet30WrapperFilter ;post類型: SendResponseFilter ; // 響應處理Filterroute類型: SendForwardFilter ; // 重定向處理Filtererror類型 : SendErrorFilter ; // 錯誤處理Filter
初始化ZuulFilterInitializer類,通過FilterLoader 將所有的Filter 向FilterRegistry註冊。我們看一下ZuulFilterInitializer類中部分代碼
public class ZuulFilterInitializer {
// 初始化完成後註冊所有的Filter
@PostConstruct
public void contextInitialized() {
log.info("Starting filter initializer");
TracerFactory.initialize(this.tracerFactory);
CounterFactory.initialize(this.counterFactory);
Iterator var1 = this.filters.entrySet().iterator();
while(var1.hasNext()) {
Entry<String, ZuulFilter> entry = (Entry)var1.next();
this.filterRegistry.put((String)entry.getKey(), (ZuulFilter)entry.getValue());
}
}
// 銷燬前移除所有註冊所有的Filter
@PreDestroy
public void contextDestroyed() {
log.info("Stopping filter initializer");
Iterator var1 = this.filters.entrySet().iterator();
while(var1.hasNext()) {
Entry<String, ZuulFilter> entry = (Entry)var1.next();
this.filterRegistry.remove((String)entry.getKey());
}
this.clearLoaderCache();
TracerFactory.initialize((TracerFactory)null);
CounterFactory.initialize((CounterFactory)null);
}
}