网关zuul 1.3.1

一、@EnableZuulProxy

@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {

}
@Configuration(proxyBeanMethods = false)
public class ZuulProxyMarkerConfiguration {
    //标记类
    @Bean
    public Marker zuulProxyMarkerBean() {
        return new Marker();
    }

    class Marker {

    }

}    

控制自动装配开启的标记类,还有一个类似的@EnableZuulServer注解,作用类似,起到zuul开启的控制作用,但是如果使用@EnableZuulServer注解,会少初始化三个过滤器PreDecorationFilter,RibbonRoutingFilter,SimpleHostRoutingFilter。当Zuul与Eureka、Ribbon等组件配合使用时,我们使用@EnableZuulProxy,如果非必要使用@EnableZuulServer即可。

二、自动装配

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration,\
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration

ZuulProxyAutoConfiguration

@Configuration(proxyBeanMethods = false)
//导入了三种发送请求的客户端 @Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.
class, RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class, RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class, HttpClientConfiguration.class }) @ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class) public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration { }

继承自ZuulServerAutoConfiguration,所以ZuulProxyAutoConfiguration相当于扩展了ZuulServerAutoConfiguration,重写了一部分逻辑,多初始化了一些过滤器。

zuul的本质还是一个servlet,遵从着mvc架构,因此我们来看看一些组件的初始化。

    //两个参数,路由、控制器
    @Bean
    public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes,
            ZuulController zuulController) {
        //初始化handlerMapping
        ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController);
        //错误请求控制器
        mapping.setErrorController(this.errorController);
        //跨域配置
        mapping.setCorsConfigurations(getCorsConfigurations());
        return mapping;
    }
    //控制器初始化
    @Bean
    public ZuulController zuulController() {
        return new ZuulController();
    }
    //servlet初始化
    @Bean
    @ConditionalOnMissingBean(name = "zuulServlet")
    @ConditionalOnProperty(name = "zuul.use-filter", havingValue = "false",
            matchIfMissing = true)
    public ServletRegistrationBean zuulServlet() {
        ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean<>(
                new ZuulServlet(), this.zuulProperties.getServletPattern());
        // buffer缓冲 false
        servlet.addInitParameter("buffer-requests", "false");
        return servlet;
    }
    
    
    //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);
    }

初始化过滤器

    @Configuration(proxyBeanMethods = false)
    protected static class ZuulFilterConfiguration {

        //从spring容器中获取所有的filters
        @Autowired
        private Map<String, ZuulFilter> filters;

        @Bean
        public ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory,
                TracerFactory tracerFactory) {
            FilterLoader filterLoader = FilterLoader.getInstance();
            FilterRegistry filterRegistry = FilterRegistry.instance();
            //过滤器放入ZuulFilterInitializer
            return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory,
                    filterLoader, filterRegistry);
        }

    }

三、执行过程

    public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
        try {
            init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
            
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();

            try {
                //前置过滤
                preRoute();
            } catch (ZuulException e) {
                error(e);
                postRoute();
                return;
            }
            try {
                //服务路由
                route();
            } catch (ZuulException e) {
                error(e);
                postRoute();
                return;
            }
            try {
                //后置过滤
                postRoute();
            } catch (ZuulException e) {
                error(e);
                return;
            }

        } catch (Throwable e) {
            error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
        } finally {
            RequestContext.getCurrentContext().unset();
        }
    }

源码较为简单,就不看了。

四、替换okhttp

跟之前讲过的feign替换类似

添加jar包

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
        </ dependency>

修改配置

ribbon.httpclient.enabled = false
ribbon.okhttp.enabled = true

 

posted @ 2022-01-17 11:48  上官兰夏  阅读(58)  评论(0编辑  收藏  举报