前言
在之前的章节我们详细分析了Zuul的Filter,这一章节我们来详细跟一下Zuul的执行流程
Zuul的执行流程是这样的
- 首先请求进来会先到达ZuulController ,ZuulController把请求交给ZuulServlet去处理
- 在ZuulServelt会调用 ZuulRunner 依次执行: init初始化,pre前置filter,route路由filter,post后置filter, error 异常filter
- ZuulRunner通过 FilterProcessor 去执行各种Filter,FilterProcessor通过 FilterLoader 加载 各种filters
- 执行完成之后,把结果响应给客户端
在上一章节我们分析了Zuul中的各种filter,那这一章我们来跟踪一下zuul的执行流程。那么入口肯定是我们的 ZuulServlet ,他类似于 DispatcherServlet 在请求的最前面做分发。我们来看一下他的源码
Zuul执行流程
1.ZuulController
请求入口
ZuulController
是请求的入口,把请求交给ZuulServlet
去处理,ZuulServlet 类似于 DispatcherServlet 在请求的最前面做分发
publicclassZuulControllerextendsServletWrappingController { publicZuulController() { //1.为父类的serveltClass 做初始化,是一个 ZuulServletsetServletClass(ZuulServlet.class); setServletName("zuul"); setSupportedMethods((String[]) null); // Allow all } publicModelAndViewhandleRequest(HttpServletRequestrequest, HttpServletResponseresponse) throwsException { try { // We don't care about the other features of the base class, just want to// handle the request//2.请求交个父类returnsuper.handleRequestInternal(request, response); } finally { // @see com.netflix.zuul.context.ContextLifecycleFilter.doFilterRequestContext.getCurrentContext().unset(); } } }
下面是它父类的源码
publicclassServletWrappingControllerextendsAbstractControllerimplementsBeanNameAware, InitializingBean, DisposableBean { privateClass<?extendsServlet>servletClass; privateStringservletName; privatePropertiesinitParameters=newProperties(); privateStringbeanName; //servletInstance 就是 ZuulServeltprivateServletservletInstance; ...省略... publicvoidafterPropertiesSet() throwsException { if (this.servletClass==null) { thrownewIllegalArgumentException("'servletClass' is required"); } else { if (this.servletName==null) { this.servletName=this.beanName; } //1.反射,根据 servletClass 创建实例this.servletInstance= (Servlet)ReflectionUtils.accessibleConstructor(this.servletClass, newClass[0]).newInstance(); this.servletInstance.init(newServletWrappingController.DelegatingServletConfig()); } } protectedModelAndViewhandleRequestInternal(HttpServletRequestrequest, HttpServletResponseresponse) throwsException { Assert.state(this.servletInstance!=null, "No Servlet instance"); //2.调用ZuulServelt的service方法this.servletInstance.service(request, response); returnnull; } }
2.ZuulServlet
请求的分发
在ZuulServelt
会调用 ZuulRunner
依次执行: init初始化,pre前置filter,route路由filter,post后置filter, error 异常filter,ZuulServlet
源码如下
/**1.核心Zuul servlet,可初始化和协调zuulFilter执行* Core Zuul servlet which intializes and orchestrates zuulFilter execution** @author Mikey Cohen* Date: 12/23/11* Time: 10:44 AM*/publicclassZuulServletextendsHttpServlet { privatestaticfinallongserialVersionUID=-3374242278843351500L; privateZuulRunnerzuulRunner; //初始化 ZuulRunner publicvoidinit(ServletConfigconfig) throwsServletException { super.init(config); StringbufferReqsStr=config.getInitParameter("buffer-requests"); booleanbufferReqs=bufferReqsStr!=null&&bufferReqsStr.equals("true") ?true : false; zuulRunner=newZuulRunner(bufferReqs); } //请求执行核心方法publicvoidservice(javax.servlet.ServletRequestservletRequest, javax.servlet.ServletResponseservletResponse) throwsServletException, IOException { try { //初始化 , 调用zuulRunner的init方法,//主要是把ServletRequest请求对象设置给RequestContext上下文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 attachedRequestContextcontext=RequestContext.getCurrentContext(); //将此请求标记为“ Zuul引擎”,而不是servletcontext.setZuulEngineRan(); try { //执行pre的filterpreRoute(); } catch (ZuulExceptione) { //如果异常了会走 error的filter,然后再走post的filtererror(e); postRoute(); return; } try { //执行route的filterroute(); } catch (ZuulExceptione) { //如果异常了会走 error的filter,然后再走post的filtererror(e); postRoute(); return; } try { //执行post的filterpostRoute(); } catch (ZuulExceptione) { //如果异常了会走 error的filter,不会再走post的filtererror(e); return; } } catch (Throwablee) { //如果异常了会走 error的filter,默认错误码500error(newZuulException(e, 500, "UNHANDLED_EXCEPTION_"+e.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } } /*** executes "post" ZuulFilters** @throws ZuulException*///调用zuulRunner执行 post filtervoidpostRoute() throwsZuulException { zuulRunner.postRoute(); } /*** executes "route" filters** @throws ZuulException*///调用zuulRunner执行 route filtervoidroute() throwsZuulException { zuulRunner.route(); } /*** executes "pre" filters** @throws ZuulException*///调用zuulRunner执行 pre filtervoidpreRoute() throwsZuulException { zuulRunner.preRoute(); } /*** initializes request** @param servletRequest* @param servletResponse*///调用zuulRunner执行 初始化 ,主要是把servletRequest设置给ReqestContext上下文对象voidinit(HttpServletRequestservletRequest, HttpServletResponseservletResponse) { zuulRunner.init(servletRequest, servletResponse); } /*** sets error context info and executes "error" filters** @param e*///通过RequestContext设置异常//通过zuulRunner执行 error filtervoiderror(ZuulExceptione) { RequestContext.getCurrentContext().setThrowable(e); zuulRunner.error(); } }
3.ZuulRunner
执行器
上面涉及到一个非常重要的类ZuulRunner
所有的请求都是通过它来执行的,此类将Servlet请求和响应初始化到RequestContext中,并将FilterProcessor调用包装为preRoute(),route(),postRoute()和error()方法 ,我们看一下ZuulRunner的源码
/*** This class initializes servlet requests and responses into the RequestContext and wraps the FilterProcessor calls* to preRoute(), route(), postRoute(), and error() methods** @author mikey@netflix.com* @version 1.0*/publicclassZuulRunner { privatebooleanbufferRequests; /*** Creates a new <code>ZuulRunner</code> instance.*/publicZuulRunner() { this.bufferRequests=true; } /**** @param bufferRequests - whether to wrap the ServletRequest in HttpServletRequestWrapper and buffer the body.在ZuulServlet中创建ZuulRunner的时候传入的配置参数 bufferRequests,它决定了是否把 ServletRequest包装在HttpServletRequestWrapper中并缓冲主体。*/publicZuulRunner(booleanbufferRequests) { this.bufferRequests=bufferRequests; } /*** sets HttpServlet request and HttpResponse设置 请求对象和响应对象到 RequestContext 中* @param servletRequest* @param servletResponse*/publicvoidinit(HttpServletRequestservletRequest, HttpServletResponseservletResponse) { RequestContextctx=RequestContext.getCurrentContext(); if (bufferRequests) { //把 ServletRequest包装在HttpServletRequestWrapper中并缓冲主体。ctx.setRequest(newHttpServletRequestWrapper(servletRequest)); } else { ctx.setRequest(servletRequest); } ctx.setResponse(newHttpServletResponseWrapper(servletResponse)); } //这里通过 FilterProcessor 执行器调用各种 ZuulFilters/*** executes "post" filterType ZuulFilters** @throws ZuulException*/publicvoidpostRoute() throwsZuulException { FilterProcessor.getInstance().postRoute(); } /*** executes "route" filterType ZuulFilters** @throws ZuulException*/publicvoidroute() throwsZuulException { FilterProcessor.getInstance().route(); } /*** executes "pre" filterType ZuulFilters** @throws ZuulException*/publicvoidpreRoute() throwsZuulException { FilterProcessor.getInstance().preRoute(); } /*** executes "error" filterType ZuulFilters*/publicvoiderror() { FilterProcessor.getInstance().error(); } }
4.FilterProcessor
filter执行器
继续跟踪一下 FilterProcessor的源码
publicclassFilterProcessor { ...省略代码... /*** runs "post" filters which are called after "route" filters. ZuulExceptions from ZuulFilters are thrown.* Any other Throwables are caught and a ZuulException is thrown out with a 500 status code** @throws ZuulException*/publicvoidpostRoute() throwsZuulException { try { //执行 post 类型的filterrunFilters("post"); } catch (ZuulExceptione) { throwe; } catch (Throwablee) { thrownewZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_POST_FILTER_"+e.getClass().getName()); } } /*** runs all "error" filters. These are called only if an exception occurs. Exceptions from this are swallowed and logged so as not to bubble up.*/publicvoiderror() { try { //执行 error 类型的filterrunFilters("error"); } catch (Throwablee) { logger.error(e.getMessage(), e); } } /*** Runs all "route" filters. These filters route calls to an origin.** @throws ZuulException if an exception occurs.*/publicvoidroute() throwsZuulException { try { //执行 post 类型的filterrunFilters("post"); } catch (ZuulExceptione) { throwe; } catch (Throwablee) { thrownewZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_ROUTE_FILTER_"+e.getClass().getName()); } } /*** runs all "pre" filters. These filters are run before routing to the orgin.** @throws ZuulException*/publicvoidpreRoute() throwsZuulException { try { //执行 pre 类型的filterrunFilters("pre"); } catch (ZuulExceptione) { throwe; } catch (Throwablee) { thrownewZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_"+e.getClass().getName()); } } /*** runs all filters of the filterType sType/ Use this method within filters to run custom filters by type** @param sType the filterType.* @return* @throws Throwable throws up an arbitrary exception*///执行Filter的核心方法,运行所有过滤器/在过滤器中使用此方法可按类型运行自定义过滤器publicObjectrunFilters(StringsType) throwsThrowable { if (RequestContext.getCurrentContext().debugRouting()) { Debug.addRoutingDebug("Invoking {"+sType+"} type filters"); } booleanbResult=false; //通过 FilterLoader 加载 filtersList<ZuulFilter>list=FilterLoader.getInstance().getFiltersByType(sType); if (list!=null) { for (inti=0; i<list.size(); i++) { ZuulFilterzuulFilter=list.get(i); //拿到每个filter,调用 processZuulFilter 去执行Objectresult=processZuulFilter(zuulFilter); if (result!=null&&resultinstanceofBoolean) { bResult|= ((Boolean) result); } } } //返回结果returnbResult; } /*** Processes an individual ZuulFilter. This method adds Debug information. Any uncaught Thowables are caught by this method and converted to a ZuulException with a 500 status code.** @param filter* @return the return value for that filter* @throws ZuulException*///filter的执行方法publicObjectprocessZuulFilter(ZuulFilterfilter) throwsZuulException { RequestContextctx=RequestContext.getCurrentContext(); //获取时候开启:debugbooleanbDebug=ctx.debugRouting(); finalStringmetricPrefix="zuul.filter-"; longexecTime=0; StringfilterName=""; try { longltime=System.currentTimeMillis(); //filter的类名filterName=filter.getClass().getSimpleName(); RequestContextcopy=null; Objecto=null; Throwablet=null; if (bDebug) { Debug.addRoutingDebug("Filter "+filter.filterType() +" "+filter.filterOrder() +" "+filterName); copy=ctx.copy(); } //【重要】调用 ZuulFilter.runFilter方法真正执行FilterZuulFilterResultresult=filter.runFilter(); //拿到响应状态ExecutionStatuss=result.getStatus(); execTime=System.currentTimeMillis() -ltime; switch (s) { //执行失败caseFAILED: t=result.getException(); //将过滤器名称和状态附加到当前请求的过滤器执行历史记录中ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime); break; //执行成功caseSUCCESS: 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); } break; default: break; } if (t!=null) throwt; usageNotifier.notify(filter, s); returno; } catch (Throwablee) { if (bDebug) { Debug.addRoutingDebug("Running Filter failed "+filterName+" type:"+filter.filterType() +" order:"+filter.filterOrder() +" "+e.getMessage()); } usageNotifier.notify(filter, ExecutionStatus.FAILED); if (einstanceofZuulException) { throw (ZuulException) e; } else { ZuulExceptionex=newZuulException(e, "Filter threw Exception", 500, filter.filterType() +":"+filterName); ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime); throwex; } } } ...省略代码...
不管是前置,后置,路由,异常的Filter ,FilterProcessor
都通过 runFilters("类型");
方法去执行filter,方法中通过 FilterLoader
加载指定类型的Filter列表,然后交给 processZuulFilter
方法去执行 ,该方法最终调用ZuulFilter.runFilter();
方法去执行具体的Filter 。它会以下面的顺序去执行内置的Filter:
类型 | 过滤器 | 描述 | 顺序 |
pre | ServletDetectionFilter | 在pre过滤器中,ServletDetectionFilter是第一个执行的过滤器,检测请求是用 DispatcherServlet还是 ZuulServlet,将结果设置到RequestContext中 | -3 |
pre | Servlet30WrapperFilter | 主要是将原始请求进行包装,将原始的HttpServletRequest请求包装成Servlet30RequestWrapper类型 | -2 |
pre | FormBodyWrapperFilter | 同Servlet30RequestWrapper一样,也是对请求的一个包装,只不过他只包装表单数据,即:content-type中必须带有“application/x-www-form-urlencoded”或“multipart/form-data” | -1 |
error | SendErrorFilter | 这个是用来发送错误的Filter | 0 |
pre | DebugFilter | 设置请求过程是否开启debug,将当前请求上下文中的debugRouting 和debugRequest 参数设置为true |
1 |
pre | PreDecorationFilter | 基本的路由转发配置,根据uri调用哪一个route过滤器 | 5 |
route | RibbonRoutingFilter | 服务路由的过滤器,使用用Ribbon 做负载均衡,hystrix做熔断 | 10 |
route | SimpleHostRoutingFilter | 简单主机路由过滤器,如果使用url路由,则用这个过滤器 | 100 |
route | SendForwardFilter | 它使用RequestDispatcher转发请求 | 500 |
post | SendResponseFilter | SendResponseFilter是Zuul的最后一个Filter,负责最终响应结果的输出。 | 1000 |
error类型的filter在出异常的时候才会执行
5.ZuulFilter
ZuulFilter
是所有Filter的抽象类,它的接口是IZuulFilter
,它里面有四个很重要的方法
//这个是publicinterfaceIZuulFilter { //是否要执行Run方法booleanshouldFilter(); //filter的核心业务方法Objectrun() throwsZuulException; } publicabstractclassZuulFilterimplementsIZuulFilter, Comparable<ZuulFilter> { privatefinalAtomicReference<DynamicBooleanProperty>filterDisabledRef=newAtomicReference<>(); /*** to classify a filter by type. Standard types in Zuul are "pre" for pre-routing filtering,* "route" for routing to an origin, "post" for post-routing filters, "error" for error handling.* We also support a "static" type for static responses see StaticResponseFilter.* Any filterType made be created or added and run by calling FilterProcessor.runFilters(type)** @return A String representing that type*///这个是filter的类型 ,有 pre ,route,post errorabstractpublicStringfilterType(); /*** filterOrder() must also be defined for a filter. Filters may have the same filterOrder if precedence is not* important for a filter. filterOrders do not need to be sequential.** @return the int order of a filter*///这个是filter的执行顺序,越小越先执行abstractpublicintfilterOrder(); ...省略... }
详细看一下ZuulFilter
的源码
publicabstractclassZuulFilterimplementsIZuulFilter, Comparable<ZuulFilter> { ...省略... publicZuulFilterResultrunFilter() { ZuulFilterResultzr=newZuulFilterResult(); if (!isFilterDisabled()) { //调用shouldFilter方法,这是个抽象方法,子类需要复写该方法返回 bool值决定要不要执行run方法if (shouldFilter()) { Tracert=TracerFactory.instance().startMicroTracer("ZUUL::"+this.getClass().getSimpleName()); try { //调用 filter的run方法去执行,也是个抽象方法,需要子类去实现自己的业务逻辑Objectres=run(); //执行成功,包装一个成功状态的ZuulFilterResult对象返回zr=newZuulFilterResult(res, ExecutionStatus.SUCCESS); } catch (Throwablee) { t.setName("ZUUL::"+this.getClass().getSimpleName() +" failed"); //执行失败,包装一个失败状态的ZuulFilterResult对象返回zr=newZuulFilterResult(ExecutionStatus.FAILED); zr.setException(e); } finally { t.stopAndLog(); } } else { zr=newZuulFilterResult(ExecutionStatus.SKIPPED); } } returnzr; }
ZuulFilter
是个抽象类,需要具体的子类类去复写其中的四个方法,然后 ZuulFilter 做的事情就依次调用 shouldFilter
方法,如果返回true就调用 run
方法执行子类的业务逻辑,然后把结果封装成ZuulFilterResult
返回。
到这里Zuul的执行流程的跟踪就算结束了,剩下的就是具体的Filter本身的业务代码的理解了,Zuul通过依次调用这个写Filter来完成整个生命周期的执行。最后总结一下流程