Spring Cloud Zuul源码分析

如何使用Spring Cloud Zuul?

之前的文章中,我们学习了Spring Cloud Zuul如何使用,这里再回顾下:
1.引入依赖,在启动类中添加@EnableZuulProxy,声明这是一个Zuul代理。
2.注册到Eureka Server,启动服务,访问这个端口,url中带上要请求的服务名。

Spring Cloud Zuul源码分析

既然是添加了@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
 *
 * @author Spencer Gibb
 * @author Dave Syer
 */
@EnableCircuitBreaker
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyConfiguration.class)
public @interface EnableZuulProxy {
}

从注释中可以看到,这个注解会启动一个Zuul server,并且给这个Zuul server装配一些代理过滤器,下面还提到了一个@EnableZuulServer注解,这个注解可以开启一个Zuul server,但是不配置代理。@EnableZuulProxy可以看成是@EnableZuulServer的增强版。

@EnableZuulProxy注解上import了ZuulProxyConfiguration类,从名字上看,这个就是zuul代理的配置类,这个类中,定义了DiscoveryClient和其他一些负载均衡相关的类,还初始化了一些Filter。
ZuulProxyConfiguration类继承了ZuulConfiguration,这个配置类就是对zuul进行一些配置的,里面可以看到会初始化ZuulServlet和其他一些Zuul的bean以及Filter。

在ZuulConfiguration中,还有个ZuulFilterConfiguration内部类,这个内部类中会初始化ZuulFilterInitializer,存放所有的Filters。

Zuul定义了四种类型的过滤器:
1.Pre Filter
2.Route Filter
3.Post Filter
4.Error Filter

Pre过滤器是请求路由到具体的服务之前执行的,可以用来做安全验证,参数验证等操作。
Route过滤器是用来将请求路由到具体的服务上。
Post过滤器是请求已经被路由到微服务之后执行的。
如果Pre,Route和Post过滤器在执行过程中发生了异常,会由Error过滤器处理。
下面是这四种过滤器的执行顺序:
这里写图片描述

请求会先经过per filters,然后到routing filters,再去请求到具体的服务上,返回response之后,就经过post filters。如果发生异常,交给error filters。还可以自己自己定义filters。

自己定义filter,需要继承ZuulFilter抽象类,重写下面这四个方法:

public class MyFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return false;
    }

    @Override
    public Object run() {
        return null;
    }
}

其中,filterType方法,返回这个filter的类型,比如是pre类型的过滤器。
filterOrder是定义这个过滤器的执行顺序,值越小,越先执行。
shouldFIlter返回该过滤器是否开启,返回false,表示不执行这个过滤器。
run就是具体过滤器中需要执行的方法。

接下来再看下ZuulServlet:

@Override
    public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
        try {
            init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);

            // Marks this request as having passed through the "Zuul engine", as opposed to servlets
            // explicitly bound in web.xml, for which requests will not have the same data attached
            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();
        }
    }

从ZuulServlet中,也可以看出这个执行的逻辑。Zuul的主要功能,就是在这些Filter中了。

猜你喜欢

转载自blog.csdn.net/chayangdz/article/details/82697332