前言
在之前的章节我们详细分析了Zuul的Filter,这一章节我们来详细跟一下Zuul的执行流程
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
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 在请求的最前面做分发
public class ZuulController extends ServletWrappingController {
public ZuulController() {
//1.为父类的serveltClass 做初始化,是一个 ZuulServlet
setServletClass(ZuulServlet.class);
setServletName("zuul");
setSupportedMethods((String[]) null); // Allow all
}
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
// We don't care about the other features of the base class, just want to
// handle the request
//2.请求交个父类
return super.handleRequestInternal(request, response);
}
finally {
// @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
RequestContext.getCurrentContext().unset();
}
}
}
下面是它父类的源码
public class ServletWrappingController extends AbstractController implements BeanNameAware, InitializingBean, DisposableBean {
@Nullable
private Class<? extends Servlet> servletClass;
@Nullable
private String servletName;
private Properties initParameters = new Properties();
@Nullable
private String beanName;
//servletInstance 就是 ZuulServelt
@Nullable
private Servlet servletInstance;
...省略...
public void afterPropertiesSet() throws Exception {
if (this.servletClass == null) {
throw new IllegalArgumentException("'servletClass' is required");
} else {
if (this.servletName == null) {
this.servletName = this.beanName;
}
//1.反射,根据 servletClass 创建实例
this.servletInstance = (Servlet)ReflectionUtils.accessibleConstructor(this.servletClass, new Class[0]).newInstance();
this.servletInstance.init(new ServletWrappingController.DelegatingServletConfig());
}
}
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
Assert.state(this.servletInstance != null, "No Servlet instance");
//2.调用ZuulServelt的service方法
this.servletInstance.service(request, response);
return null;
}
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
*/
public class ZuulServlet extends HttpServlet {
private static final long serialVersionUID = -3374242278843351500L;
private ZuulRunner 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 {
//初始化 , 调用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 attached
RequestContext context = RequestContext.getCurrentContext();
//将此请求标记为“ Zuul引擎”,而不是servlet
context.setZuulEngineRan();
try {
//执行pre的filter
preRoute();
} catch (ZuulException e) {
//如果异常了会走 error的filter,然后再走post的filter
error(e);
postRoute();
return;
}
try {
//执行route的filter
route();
} catch (ZuulException e) {
//如果异常了会走 error的filter,然后再走post的filter
error(e);
postRoute();
return;
}
try {
//执行post的filter
postRoute();
} catch (ZuulException e) {
//如果异常了会走 error的filter,不会再走post的filter
error(e);
return;
}
} catch (Throwable e) {
//如果异常了会走 error的filter,默认错误码500
error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}
}
/**
* executes "post" ZuulFilters
*
* @throws ZuulException
*/
//调用zuulRunner执行 post filter
void postRoute() throws ZuulException {
zuulRunner.postRoute();
}
/**
* executes "route" filters
*
* @throws ZuulException
*/
//调用zuulRunner执行 route filter
void route() throws ZuulException {
zuulRunner.route();
}
/**
* executes "pre" filters
*
* @throws ZuulException
*/
//调用zuulRunner执行 pre filter
void preRoute() throws ZuulException {
zuulRunner.preRoute();
}
/**
* initializes request
*
* @param servletRequest
* @param servletResponse
*/
//调用zuulRunner执行 初始化 ,主要是把servletRequest设置给ReqestContext上下文对象
void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
zuulRunner.init(servletRequest, servletResponse);
}
/**
* sets error context info and executes "error" filters
*
* @param e
*/
//通过RequestContext设置异常
//通过zuulRunner执行 error filter
void error(ZuulException e) {
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
*/
public class ZuulRunner {
private boolean bufferRequests;
/**
* Creates a new <code>ZuulRunner</code> instance.
*/
public ZuulRunner() {
this.bufferRequests = true;
}
/**
*
* @param bufferRequests - whether to wrap the ServletRequest in HttpServletRequestWrapper and buffer the body.
在ZuulServlet中创建ZuulRunner的时候传入的配置参数 bufferRequests,
它决定了是否把 ServletRequest包装在HttpServletRequestWrapper中并缓冲主体。
*/
public ZuulRunner(boolean bufferRequests) {
this.bufferRequests = bufferRequests;
}
/**
* sets HttpServlet request and HttpResponse
设置 请求对象和响应对象到 RequestContext 中
* @param servletRequest
* @param servletResponse
*/
public void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
RequestContext ctx = RequestContext.getCurrentContext();
if (bufferRequests) {
//把 ServletRequest包装在HttpServletRequestWrapper中并缓冲主体。
ctx.setRequest(new HttpServletRequestWrapper(servletRequest));
} else {
ctx.setRequest(servletRequest);
}
ctx.setResponse(new HttpServletResponseWrapper(servletResponse));
}
//这里通过 FilterProcessor 执行器调用各种 ZuulFilters
/**
* executes "post" filterType ZuulFilters
*
* @throws ZuulException
*/
public void postRoute() throws ZuulException {
FilterProcessor.getInstance().postRoute();
}
/**
* executes "route" filterType ZuulFilters
*
* @throws ZuulException
*/
public void route() throws ZuulException {
FilterProcessor.getInstance().route();
}
/**
* executes "pre" filterType ZuulFilters
*
* @throws ZuulException
*/
public void preRoute() throws ZuulException {
FilterProcessor.getInstance().preRoute();
}
/**
* executes "error" filterType ZuulFilters
*/
public void error() {
FilterProcessor.getInstance().error();
}
4.FilterProcessor
filter执行器
继续跟踪一下 FilterProcessor的源码
public class FilterProcessor {
...省略代码...
/**
* 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
*/
public void postRoute() throws ZuulException {
try {
//执行 post 类型的filter
runFilters("post");
} catch (ZuulException e) {
throw e;
} catch (Throwable e) {
throw new ZuulException(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.
*/
public void error() {
try {
//执行 error 类型的filter
runFilters("error");
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
/**
* Runs all "route" filters. These filters route calls to an origin.
*
* @throws ZuulException if an exception occurs.
*/
public void route() throws ZuulException {
try {
//执行 post 类型的filter
runFilters("post");
} catch (ZuulException e) {
throw e;
} catch (Throwable e) {
throw new ZuulException(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
*/
public void preRoute() throws ZuulException {
try {
//执行 pre 类型的filter
runFilters("pre");
} catch (ZuulException e) {
throw e;
} catch (Throwable e) {
throw new ZuulException(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的核心方法,运行所有过滤器/在过滤器中使用此方法可按类型运行自定义过滤器
public Object runFilters(String sType) throws Throwable {
if (RequestContext.getCurrentContext().debugRouting()) {
Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
}
boolean bResult = false;
//通过 FilterLoader 加载 filters
List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
ZuulFilter zuulFilter = list.get(i);
//拿到每个filter,调用 processZuulFilter 去执行
Object result = processZuulFilter(zuulFilter);
if (result != null && result instanceof Boolean) {
bResult |= ((Boolean) result);
}
}
}
//返回结果
return bResult;
}
/**
* 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的执行方法
public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
//获取时候开启:debug
boolean bDebug = ctx.debugRouting();
final String metricPrefix = "zuul.filter-";
long execTime = 0;
String filterName = "";
try {
long ltime = System.currentTimeMillis();
//filter的类名
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();
}
//【重要】调用 ZuulFilter.runFilter方法真正执行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);
}
break;
default:
break;
}
if (t != null) throw t;
usageNotifier.notify(filter, s);
return o;
} catch (Throwable e) {
if (bDebug) {
Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + e.getMessage());
}
usageNotifier.notify(filter, ExecutionStatus.FAILED);
if (e instanceof ZuulException) {
throw (ZuulException) e;
} else {
ZuulException ex = new ZuulException(e, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);
ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
throw ex;
}
}
}
...省略代码...
不管是前置,后置,路由,异常的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
,它里面有四个很重要的方法
//这个是
public interface IZuulFilter {
//是否要执行Run方法
boolean shouldFilter();
//filter的核心业务方法
Object run() throws ZuulException;
}
public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {
private final AtomicReference<DynamicBooleanProperty> filterDisabledRef = new AtomicReference<>();
/**
* 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 error
abstract public String filterType();
/**
* 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的执行顺序,越小越先执行
abstract public int filterOrder();
...省略...
}
详细看一下ZuulFilter
的源码
public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {
...省略...
public ZuulFilterResult runFilter() {
ZuulFilterResult zr = new ZuulFilterResult();
if (!isFilterDisabled()) {
//调用shouldFilter方法,这是个抽象方法,子类需要复写该方法返回 bool值决定要不要执行run方法
if (shouldFilter()) {
Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());
try {
//调用 filter的run方法去执行,也是个抽象方法,需要子类去实现自己的业务逻辑
Object res = run();
//执行成功,包装一个成功状态的ZuulFilterResult对象返回
zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
} catch (Throwable e) {
t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
//执行失败,包装一个失败状态的ZuulFilterResult对象返回
zr = new ZuulFilterResult(ExecutionStatus.FAILED);
zr.setException(e);
} finally {
t.stopAndLog();
}
} else {
zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
}
}
return zr;
}
ZuulFilter
是个抽象类,需要具体的子类类去复写其中的四个方法,然后 ZuulFilter 做的事情就依次调用 shouldFilter
方法,如果返回true就调用 run
方法执行子类的业务逻辑,然后把结果封装成ZuulFilterResult
返回。
到这里Zuul的执行流程的跟踪就算结束了,剩下的就是具体的Filter本身的业务代码的理解了,Zuul通过依次调用这个写Filter来完成整个生命周期的执行。最后总结一下流程