从技术角度来说,Zuul的的核心就是一系列的过滤器。这些过滤器都实现了ZuulFilter接口。
Zuul的过滤器ZuulFilter与Spring的过滤器Filter有什么区别?
一,ZuulFilter
ZuulFilter是一个抽象类。ZuulFilter实现了IZuulFilter接口、Comparable接口。
继承ZuulFilter的类需要实现下面4个方法:
filterType():过滤器类型,可选值有4个,pre、route、post、error。
filterOrder():过滤器执行的优先级。当某种类型的过滤器有多个时,根据优先级依次执行。
shouldFilter():判断过滤器是否需要执行。可以通过这个方法来限制过滤器的执行条件。
run():过滤器的具体执行逻辑。
二,pre过滤器
1,ServletDetectionFilter
ServletDetectionFilter:检查请求是否经过DispatcherServlet的转发。如果经过,则把
isDispatcherServletRequest置为true,否则置为false。
2,FormBodyWrapperFilter
filterOrder=-1
解析表单数据,并为请求重新编码。
3,DebugFilter
调试过滤器。源码很简单:
RequestContext ctx =
RequestContext.getCurrentContext();
ctx.setDebugRouting(true);
ctx.setDebugRequest(true);
该过滤器可以控制debug日志的打印。如果需要打印debug日志,我们可以这样设置:
zuul.debug.request=true
这样就可以打印相关的debug日志,这对于我们定位zuul的问题有帮助。例如下面这段代码:
if(RequestContext.getCurrentContext().debugRouting()){…}
Zuul会根据debugRoute来判断是否打印这条日志信息。
4,PreDecorationFilter
根据提供的RouteLocator,设置路由地址。还会设置这些属性:requestURI、proxy、
retryable、forward.to、serviceId、Host等属性。
5,TracePreZuulFilter
结合Sleuth实现链路追踪功能。
6,Servlet30WrapperFilter
对原始请求进行包装,为什么要包装一下呢?包装就是为了拿过来,然后有必要的话方便扩展。
原始请求:HttpServletRequest
包装后请求:Servlet30RequestWrapper
三,route过滤器
1,SendForwardFilter
这个过滤器的优先级是500,在route过滤器的实现中是最大的。也就是说三个route过滤器,SendForwardFilter最后执行。
SendForwardFilter过滤器的执行需要满足下面的条件:
RequestContext中包含属性:forward.to
RequestContext中包含属性:sendForwardFilter.ran并且值为true
SendForwardFilter是根据forward.to配置的url来转发请求的。
RequestDispatcher dispatcher = cxt.getRequest().getRequestDispatcher(path);
if(dispatcher != null){
ctx.set("sendForwardFilter.ran", true);
if(!ctx.getResponse().isCommited()){
dispatcher.forward(cxt.getRequest(), ctx.getResponse());
ctx.getResponse().flushBuffer();
}
}
SendForwardFilter与下面两种过滤器的区别是:SendForwardFilter使用ApplicationDispatcher来转发请求。
2,RibbonRoutingFilter
RibbonRoutingFilter过滤器的执行需要满足下面的条件:
RequestContext中不包含属性:routeHost
RequestContext中包含属性:serviceId
RequestContext中包含属性:sendZuulResponse并且值为true
RibbonRoutingFilter与SendForwardFilter的区别是RibbonRoutingFilter使用robbin来请求微服务。
3,SimpleHostRoutingFilter
SimpleHostRoutingFilter过滤器的执行需要满足下面的条件:
RequestContext中包含属性:routeHost
RequestContext中包含属性:sendZuulResponse并且值为true
SimpleHostRoutingFilter与RibbonRoutingFilter的区别是:RibbonRoutingFilter使用robbin来请求微服务,而SimpleHostRoutingFilter是通过HttpClient来转发请求。
四,post过滤器
1,SendResponseFilter
SendResponseFilter主要做两件事:
// 从RequestContext中取出微服务的响应结果,然后封装到HttpServletResponse中。
this.addResponseHeaders();
// 把响应结果写入输出流,发送给客户端。
this.writeResponse();
五,error过滤器
1,SendErrorFilter
转发请求到/error。这里的路径是可配置的。
首先会从ZuulException中拿到具体的异常信息:
RequestContext ctx =
RequestContext.getCurrentContext();
ZuulException exception = this.findZuulException(ctx.getThrowable());
HttpServletRequest request =
ctx.getRequest();
然后把异常信息放到request,最后转发请求到指定路径。
RequestDispatcher dispatcher = request.getRequestDispatcher(this.errorPath);
if(dispatcher != null){
ctx.set("sendErrorFilter.ran", true);
if(!ctx.getResponse().isCommited()){
dispatcher.forward(request, ctx.getResponse())
}
六,Zuul内置的特殊过滤器
zuul还提供了一类特殊的过滤器,分别为:StaticResponseFilter和SurgicalDebugFilter
StaticResponseFilter:StaticResponseFilter允许从Zuul本身生成响应,而不是将请求转发到源。也就是说,Zuul接收到请求后,直接返回给客户端,不再转发给其他微服务。
SurgicalDebugFilter:SurgicalDebugFilter允许将特定请求路由到分隔的调试集群或主机。
六,Zuul过滤器的优先级
ServletDetectionFilter:-3
Servlet30WrapperFilter:-2
FormBodyWrapperFilter:-1
SendErrorFilter:0
DebugFilter:1
PreDecorationFilter:5
RibbonRoutingFulter:10
SimpleHostRoutingFilter:100
SendForwardFilter:500
SendResponseFilter:1000
网友评论