1. 程式人生 > >【springcloud】zuul 的概念和原理

【springcloud】zuul 的概念和原理

一、zuul是什麼

zuul 是netflix開源的一個API Gateway 伺服器, 本質上是一個web servlet應用

二、zuul的工作原理

1、過濾器機制

zuul的核心是一系列的filters, 其作用可以類比Servlet框架的Filter,或者AOP。

zuul把Request route到 使用者處理邏輯 的過程中,這些filter參與一些過濾處理,比如Authentication,Load Shedding等。  

Zuul提供了一個框架,可以對過濾器進行動態的載入,編譯,執行。

Zuul的過濾器之間沒有直接的相互通訊,他們之間通過一個RequestContext的靜態類來進行資料傳遞的。RequestContext類中有ThreadLocal變數來記錄每個Request所需要傳遞的資料。

Zuul的過濾器是由Groovy寫成,這些過濾器檔案被放在Zuul Server上的特定目錄下面,Zuul會定期輪詢這些目錄,修改過的過濾器會動態的載入到Zuul Server中以便過濾請求使用。

下面有幾種標準的過濾器型別:

Zuul大部分功能都是通過過濾器來實現的。Zuul中定義了四種標準過濾器型別,這些過濾器型別對應於請求的典型生命週期。

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

(2) ROUTING 務。這種過濾器用於構建傳送給微服務的請求,並使用Apache HttpClient或Netfilx Ribbon請求微服務。

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

(4) ERROR:在其他階段發生錯誤時執行該過濾器。

內建的特殊過濾器

zuul還提供了一類特殊的過濾器,分別為:StaticResponseFilter和SurgicalDebugFilter

StaticResponseFilter:StaticResponseFilter允許從Zuul本身生成響應,而不是將請求轉發到源。

SurgicalDebugFilter:SurgicalDebugFilter允許將特定請求路由到分隔的除錯叢集或主機。

自定義的過濾器

除了預設的過濾器型別,Zuul還允許我們建立自定義的過濾器型別。

例如,我們可以定製一種STATIC型別的過濾器,直接在Zuul中生成響應,而不將請求轉發到後端的微服務。

2、過濾器的生命週期

Zuul請求的生命週期如圖,該圖詳細描述了各種型別的過濾器的執行順序。

3、過濾器排程過程

在ZuulServlet類中

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        try {
            this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();

            try {
                this.preRoute();
            } catch (ZuulException var12) {
                this.error(var12);
                this.postRoute();
                return;
            }

            try {
                this.route();
            } catch (ZuulException var13) {
                this.error(var13);
                this.postRoute();
                return;
            }

            try {
                this.postRoute();
            } catch (ZuulException var11) {
                this.error(var11);
            }
        } catch (Throwable var14) {
            this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName()));
        } finally {
            RequestContext.getCurrentContext().unset();
        }
    }

三、zuul 能做什麼?

Zuul可以通過載入動態過濾機制,從而實現以下各項功能:

  • 驗證與安全保障: 識別面向各類資源的驗證要求並拒絕那些與要求不符的請求。
  • 審查與監控: 在邊緣位置追蹤有意義資料及統計結果,從而為我們帶來準確的生產狀態結論。
  • 動態路由: 以動態方式根據需要將請求路由至不同後端叢集處。
  • 壓力測試: 逐漸增加指向叢集的負載流量,從而計算效能水平。
  • 負載分配: 為每一種負載型別分配對應容量,並棄用超出限定值的請求。
  • 靜態響應處理: 在邊緣位置直接建立部分響應,從而避免其流入內部叢集。
  • 多區域彈性: 跨越AWS區域進行請求路由,旨在實現ELB使用多樣化並保證邊緣位置與使用者儘可能接近。

除此之外,Netflix公司還利用Zuul的功能通過金絲雀版本實現精確路由與壓力測試。

四、zuul 與應用的整合方式

1、ZuulServlet - 處理請求(排程不同階段的filters,處理異常等) 

ZuulServlet類似SpringMvc的DispatcherServlet,所有的Request都要經過ZuulServlet的處理

三個核心的方法preRoute(),route()postRoute(),zuul對request處理邏輯都在這三個方法裡

ZuulServlet交給ZuulRunner去執行。

由於ZuulServlet是單例,因此ZuulRunner也僅有一個例項。

ZuulRunner直接將執行邏輯交由FilterProcessor處理,FilterProcessor也是單例,其功能就是依據filterType執行filter的處理邏輯

FilterProcessor對filter的處理邏輯。

  • 首先根據Type獲取所有輸入該Type的filter,List<ZuulFilter> list
  • 遍歷該list,執行每個filter的處理邏輯,processZuulFilter(ZuulFilter filter)
  • RequestContext對每個filter的執行狀況進行記錄,應該留意,此處的執行狀態主要包括其執行時間、以及執行成功或者失敗,如果執行失敗則對異常封裝後丟擲。 
  • 到目前為止,zuul框架對每個filter的執行結果都沒有太多的處理,它沒有把上一filter的執行結果交由下一個將要執行的filter,僅僅是記錄執行狀態,如果執行失敗丟擲異常並終止執行。