天天看點

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

前段時間與小夥伴閑聊時說到他們公司的現狀,近來與将來,公司将全面把單體服務向微服務架構過渡。這裡面我們聽到了關鍵詞 --- 微服務。乍聽之下,覺得也很合理。網際網路在不斷的發展,這裡不隻是行業的發展,更是系統架構的發展。現在市面上架構大緻也經曆了這幾個階段:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

這是好事嗎?是好事,毋庸置疑。因為不跟上時代的浪潮,總會被拍死在沙灘上。但完全是好事嗎?那也不見得。

我們先要明白微服務解決了什麼問題?大方面上應該就是應用層面和人層面的問題

  • 應用層面: 單體服務的架構很簡單,項目開發和維護成本低是它無争議的優點。但是臃腫耦合又會給基礎設施帶來了過重的負擔。如果某個應用處理資源占用了大量的CPU,就會導緻其他處理資源餓死的現象,系統延遲增高,直接影響系統的可用性。
  • 人層面:獨立、多語言生态 也是微服務的标簽。在單體服務中,投入的人力資源越多不見得越高效,反而越容易出錯。但微服務不同,每個服務都是獨立出來的,團隊可以更加容易的協作開發,甚至一套系統,多個服務,多種語言,毫無沖突。
《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

但是我們凡事不能被好處蒙蔽。微服務的缺點也是一直存在的:

  • 需要考慮各個服務之間的容錯性問題
  • 需要考慮資料一緻性問題
  • 需要考慮分布式事務問題
  • ...

很多人認為微服務的核心就是在于 微。服務分的越細越好,就好像平時寫代碼的時候絲毫不考慮的單一原則,反而在服務拆分上用到淋漓盡緻。這裡就需要明白一個核心概念:微服務的關鍵不在微,而是在于合适的大小

這句話好像很簡單的樣子,但是多大才算合适的大小?這可能據不同團隊,不同項目而定。合适的大小可能取決于更少的代碼倉庫,更少的部署隊列,更少的語言... 這裡更無法一錘定音!

如果沒法做到合适的大小,而無腦的拆分服務,那麼微服務可能反而成為你項目的累贅。是以,有時全面轉型微服務反而不是好事,你覺得呢?

話題有點跑遠了,咱們努力扯回來。既然微服務已經成為主流,那麼如何設計微服務便是我們應該做的事,而不是談及微服務之時,想到的隻是與人如何争論如何拒用微服務。那麼這篇我們要講的是SpringCloud之服務網關Gateway

SpringCloud之服務網關Gateway

一、認識網關

什麼是服務網關?不要給自己當頭一棒。我們換個問法,為什麼需要服務網關?

服務網關是跨一個或多個服務節點提供單個統一的通路入口

它的作用并不是可有可無的存在,而是至關重要。我們可以在服務網關做路由轉發和過濾器的實作。優點簡述如下:

  • 防止内部服務關注暴露給外部用戶端
  • 為我們内部多個服務添加了額外的安全層
  • 減低微服務通路的複雜性
《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

根據圖中内容,我們可以得出以下資訊:

  • 使用者通路入口,統一通過網關通路到其他微服務節點
  • 服務網關的功能有路由轉發,API監控、權限控制、限流

而這些便是 服務網關 存在的意義!

1)Zuul 比較

SpringCloud Gateway 是 SpringCloud 的一個全新項目,目标是取代Netflix Zuul。它是基于 Spring5.0 + SpringBoot2.0 + WebFlux 等技術開發的,性能高于 Zuul,據官方提供的資訊來看,性能是 Zuul 的1.6倍,意在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。

SpringCloud Gateway 不僅提供了統一的路由方式(反向代理),并且基于 Filter 鍊(定義過濾器對請求過濾)提供了網關基本的功能,例如:鑒權、流量控制、熔斷、路徑重寫、日志監控等。

其實說到 Netflix Zuul,在使用或準備使用微服務架構的小夥伴應該并不陌生,畢竟Netflix 是一個老牌微服務開源者。新秀與老牌之間的争奪,如果新秀沒有點硬實力,如何讓人安心轉型!

這裡我們可以順帶了解一下 Weflux,Webflux 的出現填補了 Spring 在響應式程式設計上的空白。

可能有很多小夥伴并不知道 Webflux,小菜接下來也會出一篇關于 Webflux 的講解,實則真香!

Webflux 的響應式程式設計不僅僅是程式設計風格上的改變,而是對于一系列著名的架構都提供了響應式通路的開發包,比如 Netty、Redis(如果不知道 Netty 的實力,可以想想為什麼 Nginx 可以承載那麼大的并發,底層就是基于Netty)

那麼說這麼多,跟 Zuul 有什麼關系呢?我們可以看下 Zuul 的 IO 模型

SpringCloud 中所內建的 Zuul 版本,采用的是 Tomcat 容器,使用的是傳統的 Servlet IO 處理模型。Servlet 是由 Servlet Container 管理生命周期的。

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

但問題就在于 Servlet 是一個簡單的網絡IO模型,當請求進入到 ServletContainer就會為其綁定一個線程,在并發不高的場景下這種模型是沒有問題的,但是一旦并發上來了,線程數量就會增加。那導緻的問題就是頻繁進行上下文切換,記憶體消耗嚴重,處理請求的時間就會變長。正所謂牽一發而動全身!

而 SpriingCloud Zuul 便是基于 servlet 之上的一個阻塞式處理模型,即Spring實作了處理所有 request 請求的一個 servlet(DispatcherServlet),并由該 Servlet 阻塞式處理。雖然 SpringCloud Zuul 2.0 開始,也是用了 Netty 作為并發IO架構,但是 SpringCloud 官方已經沒有內建該版本的計劃!

注:這裡沒有推崇 Gateway 的意思,具體使用依具體項目而定

三、掌握網關

1. Gateway 依賴

最關鍵的一步便是引入網關的依賴

<!--gateway網關-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
           

2. 項目結構

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

我這裡簡單的建立了一個微服務項目,項目裡有一個 store-gateway 服務網關 和一個 store-order 訂單服務。因為我們這篇隻說明服務網關的作用,不需要太多服務提供者和消費者!

在store-order訂單服務中隻有一個控制器OrderController,裡面也隻有一個簡單到發指的API

@RestController
@RequestMapping("order")
public class OrderController {

    @GetMapping("/{id:.+}")
    public String detail(@PathVariable String id) {
        return StringUtils.join("擷取到了ID為", id, "的商品");
    }

}
           

我們分别啟動兩個服務,然後通路訂單服務的API:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

結果肯定是符合預期的,不至于翻車。8001 是訂單服務的接口,這個時候我們可以了解到,原來微服務架構每個服務獨立啟動,都是可以獨立通路的,也就相當于傳統的單體服務。

我們想想看,如果用端口來區分每個服務,是否也可以達到微服務的效果?理論上好像是可以的,但是如果成百上千個服務呢?端口爆炸,維護爆炸,治理爆炸... 不說别的,心态直接爆炸了!這個時候我們就想着如果隻用統一的一個端口通路各個服務,那該多好!端口一緻,路由字首不一緻,通過路由字首來區分服務,這種方式将我們帶入了服務網關的場景。是的,這裡就說到了服務網關的功能之一 --- 路由轉發。

3. 網關出現

既然要用到網關,那我們上面建立的服務之一 store-gateway 就派上用場了!怎麼用?我們在配置檔案做個簡單的修改:

spring:
  application:
    name: store-gateway
  cloud:
    gateway:
      routes: 
        - id: store-order 
          uri: http://localhost:8001 
          order: 1
          predicates:
            - Path=/store-order/** 
          filters:
            - StripPrefix=1
           

不多廢話,我們直接啟動網關,通過通路 http://localhost:8000/store-order/order/123 看是否能擷取到訂單?

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

很順利,我們成功拿到了ID 為 123 的訂單商品!

我們看下 URL 的組成:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

能夠通路到我們的服務,說明網關配置生效了,我們再來看下這麼配置項是怎麼一回事!

spring.cloud.gateway 這個是服務網關 Gateway 的配置字首,沒什麼好說的,自己需要記住就是了。

routes 以下就是我們值得關注的了,routes 是個複數形式,那麼可以肯定,這個配置項是個數組的形式,是以意味着我們可以配多個路由轉發,當請求滿足什麼條件的時候轉到哪個微服務上。

  • id: 目前路由的唯一辨別
  • uri: 請求要轉發到的位址
  • order:路由的優先級,數字越小級别越高
  • predicates: 路由需要滿足的條件,也是個數組(這裡是或的關系)
  • filters: 過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改

了解完必要的參數,我們也高高興興去部署使用了,但是好景不長,我們又迎來了新的問題。我訂單服務原先使用的 8001 端口,因為某些原因給其他服務使用了,這個時候小腦袋又大了,這種情況肯定不會出現 上錯花轎嫁對郎 的結果!

咱們想想看這種問題要怎麼解決比較合适?既然都采用微服務了,那我們能不能采用服務名的方式跳轉通路,這樣子無論端口怎麼變,都不會影響到我們的正常業務!那如果采用服務的方式,就需要一個注冊中心,這樣子我們啟動的服務可以同步到注冊中心的 系統資料庫 中,這樣子網關就可以根據 服務名 去注冊中心中尋找服務進行路由跳轉了!那咱們就需要一個注冊中心,這裡就采用 Nacos 作為注冊中心.

關于 Nacos 的了解,可以空降 微服務新秀之Nacos,看了就會,我說的!

我們分别在服務網關 和 訂單服務的配置檔案都做了以下配置:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

啟動兩個服務後,我們可以在 Nacos 的控制台服務清單中看到兩個服務:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

這個時候可以看到 訂單服務 的服務名為:store-order,那我們就可以在網關配置檔案部分做以下修改:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

這裡的配置與上述不同點之一 http 換成了 lb(lb 指的是從nacos中按照名稱擷取微服務,并遵循負載均衡政策),之二 端口 換成了 服務名

那我們繼續通路上述URL看是否能夠成功通路到訂單服務:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

結果依然沒有翻車!這樣子,不管訂單服務的端口如何改變,隻要我們的服務名不變,那麼始終都可以通路到我們的對應的服務!

日子一天一天的過去~ 服務也一點一點的增加!終于有一天小菜煩了,因為每次增加服務都得去配置檔案中增加一個routes 的配置列,雖然也隻是 CV 的操作,但是,哪一天小菜不小心手一抖,那麼~~~ 算了算了,找找看有沒有什麼可以偷懶的寫法,終于不負小菜心,找到了一種簡化版!配置如下:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

就這?是的,就這!管你服務再怎麼多,我配置檔案都不用修改。這樣子配置的目的便是請求統一方式都是變成了 網關位址:網關端口/服務名/接口名 的方式通路。再次通路頁面,依然行得通!

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

但是友善歸友善,在友善的同時也限制了很多擴充功能,是以使用需三思!不可貪懶!

四、掌握核心

上面已經說完了網關的簡單使用,看完的小夥伴肯定已經可以上手了!接下來我們繼續趁熱打鐵,了解下 Gateway 網關的核心。不說别的,路由轉發 肯定是網關的核心!我們從上面已經了解到一個具體路由資訊載體,主要定義了以下幾個資訊(回憶下):

  • id: 路由的唯一辨別,差別于其他Route
  • uri: 路由指向目的地 uri,即用戶端請求最終被轉發到的微服務
  • order: 用于多個 Route 之間的排序,數值越小排序越靠前,比對優先級越高
  • predicate: 用來進行條件判斷,隻有斷言都傳回真,才會真正的執行路由
  • filter: 過濾器用于修改請求和響應資訊

這裡來梳理一下通路流程:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

這張圖很清楚的描述服務網關的調用流程(盲目自信)

  1. GatewayClient 向 GatewayServer 送出請求
  2. 請求首先會被 HttpWebHandlerAdapter 進行提取組轉成網關上下文
  3. 然後網關的上下文會傳遞到 DispatcherHandler,它負責将請求分發給RoutePredicateHandlerMapping
  4. RoutePredicateHandlerMapping負責路由查找,并更具路由斷言判斷路由是否可用
  5. 如果斷言成功,由 FilteringWebHandler 建立過濾器鍊并調用
  6. 請求會一次經過 PreFilter ---> 微服務 ---> PostFilter 的方法,最終傳回響應

過程了解了,我們抽取一下其中的關鍵!斷言 和 過濾器

1. 斷言

Predicate 也就是斷言,主要适用于進行條件判斷,隻有斷言都傳回真,才會真正執行路由

1)斷言工廠

SpringCloud Gateway 中内置了許多斷言工廠,所有的這些斷言都和 HTTP 請求不同的屬性相比對,具體如下;

  • 基于 Datetime 類型的斷言工廠

該類型的斷言工廠是根據時間做判斷的

1、 AfterRoutePredicateFactory: 接收一個日期參數,判斷請求日期是否晚于指定日期

2、**

BeforeRoutePredicateFactory:**接收一個日期參數,判斷請求日期是否早于指定日期

3、**

BetweenRoutePredicateFactory:**接收兩個日期參數,判斷請求日期是否在指定時間段内

  • 基于遠端位址的斷言工廠 RemoteAddrRoutePredicateFactory

該類型的斷言工廠是接收一個參數,IP 位址端,判斷請求主機位址是否在位址段中。(eq:-RemoteAddr=192.168.1.1/24)

  • 基于Cookie的斷言工廠 CookieRoutePredicateFactory

該類型的斷言工廠接收兩個參數,Cookie 名字和一個正規表達式,判斷請求 cookie 是否具有給定名稱且值與正規表達式比對。(eq:-Cookie=cbuc)

  • 基于Header的斷言工廠HeaderRoutePredicateFactory

該類型的斷言工廠接收兩個參數,标題名稱和正規表達式。判斷請求 Header 是否具有給定名稱且值與正規表達式比對。(eq:-Header=X-Request)

  • 基于Host的斷言工廠 HostRoutePredicateFactory

該類型的斷言工廠接收一個參數,主機名模式。判斷請求的host 是否滿足比對規則。(eq:-Host=**.cbuc.cn)

  • 基于Method請求方法的斷言工廠 MethodRoutePredicateFactory

該類型的斷言工廠接收一個參數,判斷請求類型是否跟指定的類型比對。(eq:-Method=GET)

  • 基于Path請求路徑的斷言工廠 PathRoutePredicateFactory

該類型的斷言工廠接收一個參數,判斷請求的URI部分是否滿足路徑規則。(-eq:-Path=/order/)

  • 基于Query請求參數的斷言工廠 QueryRoutePredicateFactory

該類型的斷言工廠接收兩個參數,請求 Param 和 正規表達式。判斷請求參數是否具有給定名稱且值與正規表達式比對。(eq:-Query=cbuc)

  • 基于路由權重的斷言工廠 WeightRoutePredicateFactory

該類型的斷言工廠接收一個[組名,權重],然後對于同一個組内的路由按照權重轉發

2)使用

這麼多斷言工廠,這裡就不一一使用示範了,我們結合幾個斷言工廠的使用示範一下。

我們老樣子不多廢話,直接上代碼:

CustomPredicateRouteFactory

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

配置檔案

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

測試結果

success

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

fail

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

驚呼 Amazing 的同時,不要着急的往下看,我們回歸代碼,看看,為什麼一個可以通路成功,一個卻通路失敗了。兩個方面:1. 兩者通路的URL有哪些不同 2. 代碼哪部分對 URL 做出了處理

先養成獨立思考,再去看解決方法

當你思考完後,可能部分同學已經有結果了,那讓我們繼續往下看!首先是一個 CustomRoutePredicateFactory類,這個類的作用有點像攔截器,在做請求轉發的時候進行了攔截,我們請求的時候可以打個斷點:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

可以看到,确實是攔截器的功能,在每個請求發起的時候做了攔截。那問題2 的結果就出來了,原來URL處理是在 RoutePredicateFactory 中做了處理,在 apply 方法中可以通過 exchange.getRequest() 拿到 ServerHttpRequest 對象,進而可以擷取到請求的參數、請求方式、請求頭等資訊。shortcutFieldOrder()方法也是重寫的關鍵之一,我們需要這裡傳回,我們實體類中定義的屬性,然後在apply()方法中才能接收到我們指派的屬性參數!

注意:如果自定義的實體中有多個屬性需要判斷,shortcutFieldOrder()方法中的順序要跟配置檔案中的參數順序一緻

那麼當我們編寫了該斷言工廠後,如果讓之生效?@Component 這個注解肯定必不可少了,目的就是讓 Spring 容器管理。那麼已經注冊的斷言工廠如何聲明使用呢?那就得回到配置檔案了!

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

我們這裡重點看 predicates 這個配置項下的配置,分别有三個配置,一個是我們已經熟悉的Path ,其他兩個有點陌生,但是這裡再看看 Custom 是不是又有點眼熟?是的,我們在上面好像定義了一個叫 CustomRoutePredicate 的斷言工廠,兩者有點相似,又好像差點什麼。那我就再給你一個提示:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

我們看下抽象的斷言工廠有哪些自實作的類!其中是不是有 PathRoutePredicateFactory,沒錯,就是你想的那樣!有沒有一種撥開雨霧見青天的感覺!原來我們配置檔案的 key 是以類名的字首聲明的,也就是說斷言工廠類的格式必須是:自定義名稱+ RoutePredicateFactory為字尾,然後在配置檔案中聲明。這樣子舉一反三,我們自然而然的就清楚了 - Before 的作用,該作用便是:限制請求時間在 xxx 之前。

而 - Custom=cbuc,這個 cbuc 便是我們限制的規則,隻有 name 為 cbuc 的使用者才能請求成功。如果有多個參數,可以用, 隔開,順序需要與斷言工廠中shortcutFieldOrder() 傳回參數的順序一緻!

如果在自定義斷言工廠的途中遇到了什麼阻礙,不然看看内置的斷言工廠是如何實作的。多看源碼總沒錯!

2. 過濾器

接下來進入第二個核心,也就是過濾器。該核心的作用也挺簡單,就是在請求的傳遞過程中,對請求和響應做一系列的手腳。為了怕你劃回去看請求流程過于麻煩,小菜貼心的再貼一遍流程圖:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

在 Gateway 的過濾器中又可以分為 局部過濾器 和 全局過濾器。聽名稱就知道其作用,局部是用于某一個路由上的,全局 是用于所有路由上的。不過不管是 局部 還是 全局,生命周期都分為 pre 和 post。

  • pre: 作用于路由到微服務之前調用。我們可以利用這種過濾器實作身份驗證、在叢集中選擇請求的微服務,記錄調試記錄等
  • post: 作用于路由到微服務之後執行。我們可以利用這種過濾器用來響應添加标準的 HTTP Header,收集統計資訊和名額、将響應從微服務發送到用戶端。

1)局部過濾器

局部過濾器是針對于單個路由的過濾器。同樣 Gateway 已經内置了許多過濾器

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

我們選幾種常用的過濾器進行說明:(下列過濾器省略字尾 GaewayFilterFactory,完整名稱為 字首+字尾)

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

内置的過濾器小夥伴們可以自己嘗試一番,有問題歡迎提問!

我們接下來講講如何自定義過濾器工廠。don't say so much,我們上代碼

CustomGatewayFilterFactory

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

配置檔案

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

當我們開啟請求計數的時候,可以看到控制台對于請求次數作了統計:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

是以我們可以通過這種方式輕松實作局部過濾器

2)全局過濾器

全局過濾器作用于所有路由,無需配置。通過全局過濾器可以實作對權限的統一校驗,安全性驗證等功能

老樣子,我們先看看 Gateway 中存在哪些全局過濾器:

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

相對于局部過濾器,全局過濾器的命名就沒有太多限制了,畢竟不需要在配置檔案中進行配置。

我們熟悉一下經典的全局過濾器

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

了解完内置的過濾器,我們再看看如何定義全局的過濾器!

CustomerGlobalFilter

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

對于全局過濾器,我們不需要在配置檔案中配置,因為是作用于所有路由

測試結果

success

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

fail

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

可以看到,我們使用全局過濾器進行了鑒權處理,如果沒有攜帶 token 将無法通路!

《吃透微服務》—服務網關之GatewaySpringCloud之服務網關Gateway一、認識網關1)Zuul 比較三、掌握網關1. Gateway 依賴2. 項目結構3. 網關出現四、掌握核心1. 斷言1)斷言工廠2)使用2. 過濾器1)局部過濾器2)全局過濾器

image

到這裡我們已經了解到了服務網關的路由轉發,權限校驗甚至于可以基于斷言和過濾器做出粗略簡單的 API監控和限流

但其實對于 API監控和 限流,SpringCloud 中已經有了更好的元件完成這兩項工作。畢竟單一原則,做的越多往往錯的也越多!