SpringCloud之Zuul:微服務系統架構網關

目錄

 

1. 什麼是Zuul?

2. Zuul深入剖析

2.1 過濾器

2.2 源碼理解

3. Zuul應用場景

3.1 Zuul如何實現路由轉發?

3.2 Zuul如何實現限流熔斷?

3.3 Zuul如何進行壓力測試

4. Zuul2.0概述


1. 什麼是Zuul?

Zuul是從設備、網站到應用程序後端的所有請求的前門。作爲邊緣服務應用程序,Zuul旨在實現動態路由,監控,彈性和安全性。

Zuul使用了各種不同類型的過濾器,這使我們能夠快速靈活地將功能應用於邊緣服務。這些過濾器幫助我們執行以下功能:

  • 安全認證-識別每個資源的身份驗證要求,並拒絕不滿足要求的請求。
  • 日誌監控-跟蹤某些數據和統計信息,以便爲我們提供準確的生產視圖。
  • 路由轉發-根據需要將請求動態路由到不同的後端羣集。
  • 壓力測試-逐漸增加到羣集的流量以評估性能。
  • 限流-爲每種類型的請求分配容量,並丟棄超出限制的請求。
  • 熔斷-直接在邊緣構建一些響應,而不是將其轉發到內部集羣

Zuul 在 Netflix 的應用場景:

 

2. Zuul深入剖析

Zuul 是基於 Servlet 開發的,通過 Zuul 的核心構架圖可以看出 Zuul 是由很多的過濾器組成的。

2.1 過濾器

Filter是Zuul的核心,用來實現對外服務的控制。Filter的生命週期有4個,分別是“PRE”、“ROUTING”、“POST”、“ERROR”,整個生命週期可以用下圖來表示。

 

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

  • PRE:這種過濾器在請求被路由之前調用。我們可利用這種過濾器實現身份驗證、在集羣中選擇請求的微服務、記錄調試信息等。
  • ROUTING:這種過濾器將請求路由到微服務。這種過濾器用於構建發送給微服務的請求,並使用Apache HttpClient或Netfilx Ribbon請求微服務。
  • POST:這種過濾器在路由到微服務以後執行。這種過濾器可用來爲響應添加標準的HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等。
  • ERROR:在其他階段發生錯誤時執行該過濾器。

除了默認的過濾器類型,Zuul還允許我們創建自定義的過濾器類型。例如,我們可以定製一種STATIC類型的過濾器,直接在Zuul中生成響應,而不將請求轉發到後端的微服務。

2.2 源碼理解

- Zuul 是如何將各個 Filter 的處理結果連接起來的?

答:通過 RequestContext 對象,使用 ThreadLocal。

關鍵源碼:

public class RequestContext extends ConcurrentHashMap<String, Object> {
    protected static final ThreadLocal<? extends RequestContext> threadLocal = new ThreadLocal<RequestContext>() {
        @Override
        protected RequestContext initialValue() {
            try {
                return contextClass.newInstance();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
    };

    public static RequestContext getCurrentContext() {
        if (testContext != null) return testContext;

        RequestContext context = threadLocal.get();
        return context;
    }

    public StringBuilder getFilterExecutionSummary() {
        if (get("executedFilters") == null) {
            putIfAbsent("executedFilters", new StringBuilder());
        }
        return (StringBuilder) get("executedFilters");
    }

    public void unset() {
        threadLocal.remove();
    }
}

 

3. Zuul應用場景

紅綠部署、開發者測試分支、埋點測試、壓力測試、調試路由、金絲雀測試、粘性金絲雀、失敗注入測試、降級測試、跨區域高可用、防爬防攻擊、健康檢查和屏蔽壞節點。

 

以下是我在學習過程中的幾個思考。

3.1 Zuul如何實現路由轉發?

通過實現 Filter 來實現:

過濾器樣例:

public class MyFilter extends ZuulFilter {
    @Override
    String filterType() {
        return "pre"; //定義filter的類型,有pre、route、post、error四種
    }

    @Override
    int filterOrder() {
        return 10; //定義filter的順序,數字越小表示順序越高,越先執行
    }

    @Override
    boolean shouldFilter() {
        return true; //表示是否需要執行該filter,true表示執行,false表示不執行
    }

    @Override
    Object run() {
        return null; //filter需要執行的具體操作
    }
}

3.2 Zuul如何實現限流熔斷?

實現一個過濾器,run()方法爲空。

3.3 Zuul如何進行壓力測試

實現一個壓力測試的過濾器,路由指定到某個服務。

 

4. Zuul2.0概述

Zuul 1.0是基於 Servlet 來實現的,是一種 BIO 網絡通信模式。

 

這種模式優點是:模型簡單、開發調試運維簡單。

缺點是:線程上下文切換會有開銷,並且存在連接數限制。

 

基於1.0版本,Zuul 推出了 2.0版本,在網絡通信模型進行了優化(還有其他)。

採用 AIO 的模式,相比於1.0版本,在線程開銷上減小了,也能夠接入更多的連接數。

但是缺點是:編程模型變複雜的同時也提高了開發運複雜度,並且更重要的一點是基於 ThreadLocal 實現的 RequestContext 無法工作了。

 

對比2個版本,2.0的升級帶來了20%的性能提升,Zuul 1.0可以承受百億級別的流量,2.0則達到千億級。相對而言,2.0並沒有帶來很大的性能提升,並且1.0版本已經可以滿足大多業務需要,此外也可以通過使用 AsyncServlet 對1.0進行優化。因此選擇1.0版本會更合適些。

 

參考資料

- https://github.com/Netflix/zuul/wiki/How-We-Use-Zuul-At-Netflix

- 楊波極客專欄《微服務架構實戰160講》

- http://www.ityouknow.com/springcloud/2018/01/20/spring-cloud-zuul.html

 

 

 

 

 

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