Zuul源码分析

Posted south-pigeon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Zuul源码分析相关的知识,希望对你有一定的参考价值。

zuul:

用户访问zuul回首先进入zuul的什么东西里面?

用户访问SpringMvc会先进那里?DispathchServlet

在zuul里面也有一个请求转发器,ZuulServlet

技术图片

源码:

ZuulServlet继承HttpServlet

public class ZuulServlet extends HttpServlet {}
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        try {
            this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
        // 所有的请求都建立 RequestContext context
= RequestContext.getCurrentContext();
        // 给当前的访问,设置一个zuul的处理引擎 context.setZuulEngineRan();
try {
          // 先进入pre的Router,会执行系统里面的所有的ZuulFilter
          // preRoute主要做参数的校验,权限验证,限流等
this.preRoute(); } catch (ZuulException var12) {
          // 若在preRoute期间发生错误,则先进入Error的filter,其次进入postRoute,因为postRoute才能给用户响应数据
this.error(var12); this.postRoute(); return; } try {
          // zuul将用户的访问,转为由zuul构造请求去访问微服务
this.route(); } catch (ZuulException var13) { this.error(var13); this.postRoute(); return; } try {
          // zuul将微服务响应给它的数据,响应给用户
this.postRoute(); } catch (ZuulException var11) { this.error(var11); } } catch (Throwable var14) { this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } }

preRoute()

   void preRoute() throws ZuulException {
      // servlet交给ZuulRunner去执行过滤器
this.zuulRunner.preRoute(); }

zuulRunner里面的preRoute()

runner里面并没有做实际的事情,交给FilterProcessor

    public void preRoute() throws ZuulException {
        FilterProcessor.getInstance().preRoute();
    }

真正的执行方法

 public void preRoute() throws ZuulException {
        try {
            this.runFilters("pre");
        } catch (ZuulException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + var3.getClass().getName());
        }
    }
 public Object runFilters(String sType) throws Throwable {
        if (RequestContext.getCurrentContext().debugRouting()) {
            Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
        }

        boolean bResult = false;
      // 通过过滤器加载器,获取所有该类型的过滤器 ‘pre‘ List
<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType); if (list != null) { for(int i = 0; i < list.size(); ++i) { ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
          // 执行每个过滤器 Object result
= this.processZuulFilter(zuulFilter); if (result != null && result instanceof Boolean) { bResult |= (Boolean)result; } } } return bResult; }
 public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        boolean bDebug = ctx.debugRouting();
        String metricPrefix = "zuul.filter-";
        long execTime = 0L;
        String filterName = "";

        try {
            long ltime = System.currentTimeMillis();
            filterName = filter.getClass().getSimpleName();
            RequestContext copy = null;
            Object o = null;
            Throwable t = null;
            if (bDebug) {
                Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);
                copy = ctx.copy();
            }
        // 实际执行的filter
            ZuulFilterResult result = filter.runFilter();
            ExecutionStatus s = result.getStatus();
            execTime = System.currentTimeMillis() - ltime;
            switch(s) {
            case FAILED:
                t = result.getException();
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
                break;
            case SUCCESS:
                o = result.getResult();
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);
                if (bDebug) {
                    Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms");
                    Debug.compareContextState(filterName, copy);
                }
            }

            if (t != null) {
                throw t;
            } else {
                this.usageNotifier.notify(filter, s);
                return o;
            }
        } catch (Throwable var15) {
            if (bDebug) {
                Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + var15.getMessage());
            }

            this.usageNotifier.notify(filter, ExecutionStatus.FAILED);
            if (var15 instanceof ZuulException) {
                throw (ZuulException)var15;
            } else {
                ZuulException ex = new ZuulException(var15, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
                throw ex;
            }
        }
    }
public ZuulFilterResult runFilter() {
        ZuulFilterResult zr = new ZuulFilterResult();
        if (!this.isFilterDisabled()) {
            if (this.shouldFilter()) {
                Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());

                try {
            // 执行filter里面的拦截方法 Object res
= this.run(); zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS); } catch (Throwable var7) { t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed"); zr = new ZuulFilterResult(ExecutionStatus.FAILED); zr.setException(var7); } finally { t.stopAndLog(); } } else { zr = new ZuulFilterResult(ExecutionStatus.SKIPPED); } } return zr; }
public interface IZuulFilter {
    boolean shouldFilter();

    Object run() throws ZuulException;
}

zuul执行流程总结

ZuulServlet->ZuulServlet.xxxRouter->ZuulRunner.xxxRouter->FileterProcessor.getInstance().xxxRouter()

主要执行Filter的代码在filterProcessor里面完成

1. 加载执行类型的Filter列表

 List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);

2. 执行每个FIleter

FilterProcessor.processZullFilter(Filter)->Filter.runFilter->Filter.run()

 

以上是关于Zuul源码分析的主要内容,如果未能解决你的问题,请参考以下文章

zuul源码分析-探究原生zuul的工作原理

Zuul源码分析之 网关处理流程

Zuul2源码分析

Spring GateWay 路由源码分析

Zuul源码分析之 网关处理流程

Zuul源码分析之 网关处理流程