Zuul的內置過濾器詳解(源碼解析)

Zuul的內置過濾器詳解(源碼解析)

從技術角度來說,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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章