spring-cloud 原始碼 zuul 啟動(一)
阿新 • • 發佈:2019-02-16
1 依賴配置
依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
啟動
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy //啟動zuul代理,@EnableZuulServer 非代理方式啟動
public class ZuulApplication {
final static Logger logger = LoggerFactory.getLogger(ZuulApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ZuulApplication.class)
.web(true).run(args);
logger.debug(applicationContext.getId() + "已經啟動,當前host:{}" ,
applicationContext.getEnvironment().getProperty("HOSTNAME"));
}
}
2 自動啟動配置入口過程
按springboot 原始碼分析的老套路從啟動註解@EnableZuulProxy 開始
/**
* Sets up a Zuul server endpoint and installs some reverse proxy filters in it, so it can
* forward requests to backend servers. The backends can be registered manually through
* configuration or via DiscoveryClient.
*
* @see EnableZuulServer for how to get a Zuul server without any proxying
@EnableCircuitBreaker //開啟斷路器(hystrix)
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
//讓ZuulProxyMarkerConfiguration 配置生效
@Configuration
public class ZuulProxyMarkerConfiguration {
//建立Marker 例項,讓ZuulProxyMarkerConfiguration 配置生效
@Bean
public Marker zuulProxyMarkerBean() {
return new Marker();
}
class Marker {
}
}
//zuul代理配置
@Configuration
//引用建立下面三種客戶端配置
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class })
//Marker 例項存在,該配置類生效
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
//省出一大波呆碼
}
3 ZuulServerAutoConfiguration 代理配置詳解
從上面可以看到ZuulProxyAutoConfiguration 繼承ZuulServerAutoConfiguration 那麼在這裡先分析ZuulServerAutoConfiguration
//zuul 配置屬性類,如路由等資訊
@Autowired
protected ZuulProperties zuulProperties;
@Autowired
protected ServerProperties server;
//請求錯誤控制器
@Autowired(required = false)
private ErrorController errorController;
//省去一些程式碼
//組合路由定位器,將個種路由定位器進行組合
@Bean
@Primary
public CompositeRouteLocator primaryRouteLocator(
Collection<RouteLocator> routeLocators) {
return new CompositeRouteLocator(routeLocators);
}
//簡單路由定位器,作用於uri與服務地址的匹配
@Bean
@ConditionalOnMissingBean(SimpleRouteLocator.class)
public SimpleRouteLocator simpleRouteLocator() {
return new SimpleRouteLocator(this.server.getServletPrefix(),
this.zuulProperties);
}
//關網控制器,會被ZuulServlet(跟DispatchServlet類似) 通過handlerAdapter找到並被呼叫
@Bean
public ZuulController zuulController() {
return new ZuulController();
}
//HandlerMapping 一個實現,這塊完全是spring-mvc的東西
@Bean
public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController());
mapping.setErrorController(this.errorController);
return mapping;
}
@Bean
public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() {
return new ZuulServerAutoConfiguration.ZuulRefreshListener();
}
//如果zuulServlet 不存在存執行
@Bean
@ConditionalOnMissingBean(name = "zuulServlet")
public ServletRegistrationBean zuulServlet() {
ServletRegistrationBean servlet = new ServletRegistrationBean(new ZuulServlet(),
this.zuulProperties.getServletPattern());
// The whole point of exposing this servlet is to provide a route that doesn't
// buffer requests.
servlet.addInitParameter("buffer-requests", "false");
return servlet;
}
//例項化一個前置zuulfilter
@Bean
public ServletDetectionFilter servletDetectionFilter() {
return new ServletDetectionFilter();
}
//下面省去一波程式碼,主要是各中zuulfilter
4 ZuulProxyAutoConfiguration 代理配置詳解
//ribbon個性化引數設定
@SuppressWarnings("rawtypes")
@Autowired(required = false)
private List<RibbonRequestCustomizer> requestCustomizers = Collections.emptyList();
//服務釋出客戶端
@Autowired
private DiscoveryClient discovery;
//服務路由匹配器
@Autowired
private ServiceRouteMapper serviceRouteMapper;
//省去一點程式碼
//注入封裝了服務發現客戶端各路由定位器及其它一些資訊
@Bean
@ConditionalOnMissingBean(DiscoveryClientRouteLocator.class)
public DiscoveryClientRouteLocator discoveryRouteLocator() {
return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), this.discovery, this.zuulProperties,
this.serviceRouteMapper);
}
//zuul 前置過濾器
@Bean
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) {
return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), this.zuulProperties,
proxyRequestHelper);
}
// ribbon 路由過濾器,如果是使用serviceId請求服務執行該過濾器
@Bean
public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,
RibbonCommandFactory<?> ribbonCommandFactory) {
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers);
return filter;
}
// 主機地址路由器,如果發現是主要地址請求,帽執行該路由器
@Bean
@ConditionalOnMissingBean(SimpleHostRoutingFilter.class)
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties) {
return new SimpleHostRoutingFilter(helper, zuulProperties);
}
//省去一堆程式碼
到這裡,以上是zuul 啟動的基本過程,一下編將會分析zuul請求的執行過程