当前位置: 移动技术网 > IT编程>开发语言>Java > Zuul【工作原理】

Zuul【工作原理】

2019年10月26日  | 移动技术网IT编程  | 我要评论

总裁培训,高铬板锤,捧腹网每日动漫

zuul的核心逻辑都是由一系列filter过滤器链实现的,但是filter的类型不同,执行的时机也不同,效果自然也不一样,主要特点如下:

  1. filter的类型:filter的类型,决定了它在整个filter链中的执行顺序,可能在端点路由前执行,也可能在端点路由时执行,还有可能在端点路由后执行,甚至是端点路由发生异常时执行。
  2. filter的执行顺序:同一种类型的filter,可以通过filterorder()方法设置执行顺序,一般都是根据业务场景自定义filter执行顺序。
  3. filter执行条件:filter运行所需的标准,或条件。
  4. filter执行效果:符合某个filter执行条件,产生执行效果。

zuul内部有一套完整的机制,可以动态读取编译运行filter机制,filter与filter之间不直接通信,在请求线程中会通过requestcontext来共享状态,它内部是用threadlocal实现的,例如httpservletrequest、httpservletresponse、异常信息等。部分源码如下:

public class requestcontext extends concurrenthashmap<string, object> {

    private static final logger log = loggerfactory.getlogger(requestcontext.class);

    protected static class<? extends requestcontext> contextclass = requestcontext.class;

    private static requestcontext testcontext = null;

    protected static final threadlocal<? extends requestcontext> threadlocal = new threadlocal<requestcontext>() {
        @override
        protected requestcontext initialvalue() {
            try {
                return contextclass.newinstance();
            } catch (throwable e) {
                throw new runtimeexception(e);
            }
        }
    };

  //.......
}

zuul中不同类型的filter执行逻辑的核心在zuulservlet类中,主要代码如下:

public class zuulservlet extends httpservlet {

    private static final long serialversionuid = -3374242278843351500l;
    private zuulrunner zuulrunner;


    @override
    public void init(servletconfig config) throws servletexception {
        super.init(config);

        string bufferreqsstr = config.getinitparameter("buffer-requests");
        boolean bufferreqs = bufferreqsstr != null && bufferreqsstr.equals("true") ? true : false;

        zuulrunner = new zuulrunner(bufferreqs);
    }

    @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(); //如果preroute方法在执行的时候出现异常,直接就抛出500异常,不会走catch中的error方法,见下图filterprocessor类中的preroute方法。
            } catch (zuulexception e) {
                error(e); //如果preroute在执行过程中,抛出zuul异常,这里被捕捉到以后,会执行error方法,打印堆栈信息,见下图filterprocessor类中的error方法。
                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();
        }
    }

  //....... }

 

 

 

 

 

zuul一共有4种不同的生命周期:

  1. pre:在zuul网关按照规则路由到下级服务之前执行,如果需要对请求进行预处理,可以使用这种类型的过滤器。如:认证鉴权,限流等。
  2. route:这种过滤器是zuul路由动作的执行者,是apache httpclient或ribbon构建和发送原始http请求的地方,现在也支持okhttp。
  3. post:这种过滤器是在端点请求完毕,返回结果或者发生异常后执行的filter。如果需要对返回的结果进行再次处理,可以在这种过滤中处理逻辑。
  4. error: 这种过滤器是在整个生命周期内,如果发生异常,就执行该filter,可以做全局异常处理。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网