1. 程式人生 > >spring-cloud 原始碼 zuul 啟動(一)

spring-cloud 原始碼 zuul 啟動(一)

zuul 閘道器啟動原始碼分析

 

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請求的執行過程