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);
}
}