從技術(shù)角度來(lái)說(shuō),Zuul的的核心就是一系列的過(guò)濾器。這些過(guò)濾器都實(shí)現(xiàn)了ZuulFilter接口旺聚。
Zuul的過(guò)濾器ZuulFilter與Spring的過(guò)濾器Filter有什么區(qū)別?
一,ZuulFilter
ZuulFilter是一個(gè)抽象類(lèi)煎谍。ZuulFilter實(shí)現(xiàn)了IZuulFilter接口、Comparable接口阻逮。
繼承ZuulFilter的類(lèi)需要實(shí)現(xiàn)下面4個(gè)方法:
filterType():過(guò)濾器類(lèi)型粱快,可選值有4個(gè),pre叔扼、route事哭、post、error瓜富。
filterOrder():過(guò)濾器執(zhí)行的優(yōu)先級(jí)鳍咱。當(dāng)某種類(lèi)型的過(guò)濾器有多個(gè)時(shí),根據(jù)優(yōu)先級(jí)依次執(zhí)行与柑。
shouldFilter():判斷過(guò)濾器是否需要執(zhí)行谤辜。可以通過(guò)這個(gè)方法來(lái)限制過(guò)濾器的執(zhí)行條件价捧。
run():過(guò)濾器的具體執(zhí)行邏輯丑念。
二,pre過(guò)濾器
1结蟋,ServletDetectionFilter
ServletDetectionFilter:檢查請(qǐng)求是否經(jīng)過(guò)DispatcherServlet的轉(zhuǎn)發(fā)脯倚。如果經(jīng)過(guò),則把
isDispatcherServletRequest置為true嵌屎,否則置為false推正。
2,F(xiàn)ormBodyWrapperFilter
filterOrder=-1
解析表單數(shù)據(jù)宝惰,并為請(qǐng)求重新編碼植榕。
3,DebugFilter
調(diào)試過(guò)濾器尼夺。源碼很簡(jiǎn)單:
RequestContext ctx =
RequestContext.getCurrentContext();
ctx.setDebugRouting(true);
ctx.setDebugRequest(true);
該過(guò)濾器可以控制debug日志的打印尊残。如果需要打印debug日志炒瘸,我們可以這樣設(shè)置:
zuul.debug.request=true
這樣就可以打印相關(guān)的debug日志,這對(duì)于我們定位zuul的問(wèn)題有幫助夜郁。例如下面這段代碼:
if(RequestContext.getCurrentContext().debugRouting()){…}
Zuul會(huì)根據(jù)debugRoute來(lái)判斷是否打印這條日志信息什燕。
4,PreDecorationFilter
根據(jù)提供的RouteLocator竞端,設(shè)置路由地址屎即。還會(huì)設(shè)置這些屬性:requestURI、proxy事富、
retryable技俐、forward.to、serviceId统台、Host等屬性雕擂。
5,TracePreZuulFilter
結(jié)合Sleuth實(shí)現(xiàn)鏈路追蹤功能贱勃。
6井赌,Servlet30WrapperFilter
對(duì)原始請(qǐng)求進(jìn)行包裝,為什么要包裝一下呢贵扰?包裝就是為了拿過(guò)來(lái)仇穗,然后有必要的話方便擴(kuò)展。
原始請(qǐng)求:HttpServletRequest
包裝后請(qǐng)求:Servlet30RequestWrapper
三戚绕,route過(guò)濾器
1纹坐,SendForwardFilter
這個(gè)過(guò)濾器的優(yōu)先級(jí)是500,在route過(guò)濾器的實(shí)現(xiàn)中是最大的舞丛。也就是說(shuō)三個(gè)route過(guò)濾器耘子,SendForwardFilter最后執(zhí)行。
SendForwardFilter過(guò)濾器的執(zhí)行需要滿(mǎn)足下面的條件:
RequestContext中包含屬性:forward.to
RequestContext中包含屬性:sendForwardFilter.ran并且值為true
SendForwardFilter是根據(jù)forward.to配置的url來(lái)轉(zhuǎn)發(fā)請(qǐng)求的球切。
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與下面兩種過(guò)濾器的區(qū)別是:SendForwardFilter使用ApplicationDispatcher來(lái)轉(zhuǎn)發(fā)請(qǐng)求谷誓。
2,RibbonRoutingFilter
RibbonRoutingFilter過(guò)濾器的執(zhí)行需要滿(mǎn)足下面的條件:
RequestContext中不包含屬性:routeHost
RequestContext中包含屬性:serviceId
RequestContext中包含屬性:sendZuulResponse并且值為true
RibbonRoutingFilter與SendForwardFilter的區(qū)別是RibbonRoutingFilter使用robbin來(lái)請(qǐng)求微服務(wù)吨凑。
3片林,SimpleHostRoutingFilter
SimpleHostRoutingFilter過(guò)濾器的執(zhí)行需要滿(mǎn)足下面的條件:
RequestContext中包含屬性:routeHost
RequestContext中包含屬性:sendZuulResponse并且值為true
SimpleHostRoutingFilter與RibbonRoutingFilter的區(qū)別是:RibbonRoutingFilter使用robbin來(lái)請(qǐng)求微服務(wù),而SimpleHostRoutingFilter是通過(guò)HttpClient來(lái)轉(zhuǎn)發(fā)請(qǐng)求怀骤。
四,post過(guò)濾器
1焕妙,SendResponseFilter
SendResponseFilter主要做兩件事:
// 從RequestContext中取出微服務(wù)的響應(yīng)結(jié)果蒋伦,然后封裝到HttpServletResponse中。
this.addResponseHeaders();
// 把響應(yīng)結(jié)果寫(xiě)入輸出流焚鹊,發(fā)送給客戶(hù)端痕届。
this.writeResponse();
五韧献,error過(guò)濾器
1,SendErrorFilter
轉(zhuǎn)發(fā)請(qǐng)求到/error研叫。這里的路徑是可配置的锤窑。
首先會(huì)從ZuulException中拿到具體的異常信息:
RequestContext ctx =
RequestContext.getCurrentContext();
ZuulException exception = this.findZuulException(ctx.getThrowable());
HttpServletRequest request =
ctx.getRequest();
然后把異常信息放到request,最后轉(zhuǎn)發(fā)請(qǐng)求到指定路徑嚷炉。
RequestDispatcher dispatcher = request.getRequestDispatcher(this.errorPath);
if(dispatcher != null){
? ? ctx.set("sendErrorFilter.ran", true);
? ? if(!ctx.getResponse().isCommited()){
? ? ? ? dispatcher.forward(request, ctx.getResponse())
? ? }
六渊啰,Zuul內(nèi)置的特殊過(guò)濾器
zuul還提供了一類(lèi)特殊的過(guò)濾器,分別為:StaticResponseFilter和SurgicalDebugFilter
StaticResponseFilter:StaticResponseFilter允許從Zuul本身生成響應(yīng)申屹,而不是將請(qǐng)求轉(zhuǎn)發(fā)到源绘证。也就是說(shuō),Zuul接收到請(qǐng)求后哗讥,直接返回給客戶(hù)端嚷那,不再轉(zhuǎn)發(fā)給其他微服務(wù)击碗。
SurgicalDebugFilter:SurgicalDebugFilter允許將特定請(qǐng)求路由到分隔的調(diào)試集群或主機(jī)戒良。
六,Zuul過(guò)濾器的優(yōu)先級(jí)
ServletDetectionFilter:-3
Servlet30WrapperFilter:-2
FormBodyWrapperFilter:-1
SendErrorFilter:0
DebugFilter:1
PreDecorationFilter:5
RibbonRoutingFulter:10
SimpleHostRoutingFilter:100
SendForwardFilter:500
SendResponseFilter:1000