1. 程式人生 > >SpringCloud入門(八): Zuul 過濾器詳解

SpringCloud入門(八): Zuul 過濾器詳解

Zuul 過濾器

zuul 有四種過濾器型別,分別是:

1、Pre:過濾器在請求被路由之前呼叫。我們可利用這種過濾器實現身份驗證、在叢集中選擇請求的微服務、記錄除錯資訊等;

2、Routing:過濾器將請求路由到微服務。這種過濾器用於構建傳送給微服務的請求,並使用Apache HttpClient或Netfilx Ribbon請求微服;

3、Post:過濾器在路由到微服務以後執行。這種過濾器可用來為響應新增標準的HTTP Header、收集統計資訊和指標、將響應從微服務傳送給客戶端;

4、Error:在其他階段發生錯誤時執行該過濾器。除了預設的過濾器型別微服務;

 

zuul 過濾器的執行順序及生命週期(先執行pre>routing>post 然後再在同類型的過濾器按照order大小執行,越小的越先被執行),如圖:

 

 

Pre過濾器:

1、ServletDetectionFilter:是最先被執行的過濾器。主要用來檢測當前請求是通過Spring的DispatcherServlet處理執行,還是通過ZuulServlet來處理執行的。

2、Servlet30WrapperFilter:是第二個執行的過濾器,會對所有請求生效。主要用來將原始的HttpServletRequest包裝成Servlet30RequestWrapper物件;

3、FormBodyWrapperFilter:該過濾器僅對兩種類請求生效,第一類是Content-Type為application/x-www-form-urlencoded的請求,第二類是Content-Type為multipart/form-data並且是由Spring的DispatcherServlet處理的請求。主要用來將符合要求的請求體包裝成FormBodyRequestWrapper物件;

4、PreDecorationFilter:是pre階段最後被執行的過濾器。該過濾器會判斷當前請求上下文中是否存在forward.to和serviceId引數,如果都不存在,那麼它就會執行具體過濾器的操作(如果有一個存在的話,說明當前請求已經被處理過了,因為這兩個資訊就是根據當前請求的路由資訊載入進來的)。主要用來為當前請求做一些預處理,比如:進行路由規則的匹配、在請求上下文中設定該請求的基本資訊以及將路由匹配結果等一些設定資訊等,這些資訊將是後續過濾器進行處理的重要依據,我們可以通RequestContext.getCurrentContext()來訪問這些資訊。

Routing過濾器:

1、RibbonRoutingFilter:是route階段第一個執行的過濾器。該過濾器只對請求上下文中存在serviceId引數的請求進行處理,即只對通過serviceId配置路由規則的請求生效。而該過濾器的執行邏輯就是面向服務路由的核心,它通過使用Ribbon和Hystrix來向服務例項發起請求,並將服務例項的請求結果返回;

2、SimpleHostRoutingFilter:是route階段第二個執行的過濾器。該過濾器只對請求上下文中存在routeHost引數的請求進行處理,即只對通過url配置路由規則的請求生效。而該過濾器的執行邏輯就是直接向routeHost引數的實體地址發起請求,該請求是直接通過httpclient包實現的,而沒有使用Hystrix命令進行包裝,所以這類請求並沒有執行緒隔離和斷路器的保護;

3、SendForwardFilter:是route階段第三個執行的過濾器。該過濾器只對請求上下文中存在forward.to引數的請求進行處理,即用來處理路由規則中的forward本地跳轉配置;

Post過濾器:

1、SendResponseFilter:是post階段最後執行的過濾器。該過濾器會檢查請求上下文中是否包含請求響應相關的頭資訊、響應資料流或是響應體,只有在包含它們其中一個的時候就會執行處理邏輯。而該過濾器的處理邏輯就是利用請求上下文的響應資訊來組織需要傳送回客戶端的響應內容;

Error過濾器:

1、SendErrorFilter:該過濾器僅在請求上下文中包含error.status_code引數(由之前執行的過濾器設定的錯誤編碼)並且還沒有被該過濾器處理過的時候執行。而該過濾器的具體邏輯就是利用請求上下文中的錯誤資訊來組織成一個forward到API閘道器/error錯誤端點的請求來產生錯誤響應;

如何自定義過濾器

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

@Component
public class CustomFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        System.out.println("通過自定義的路由器.......");
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        return null;
    }
}

備註:ctx 在往前臺返回內容時中文會出現亂碼,ctx.getResponse().setContentType("text/html;charset=UTF-8");

如何禁用過濾器

zuul.CustomFilter.pre.disable = true

&n