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
ZuulRunner
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 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 {
private final AtomicReference 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 {
…省略…
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;
}