Gateway網關工作原理及使用方法

1. 什麼是 API 網關(API Gateway)

分佈式服務架構、微服務架構與 API 網關

在微服務架構裡,服務的粒度被進一步細分,各個業務服務可以被獨立的設計、開發、測試、部署和管理。這時,各個獨立部署單元可以用不同的開發測試團隊維護,可以使用不同的編程語言和技術平臺進行設計,這就要求必須使用一種語言和平 臺無關的服務協議作為各個單元間的通訊方式。

API 網關的定義

網關的角色是作為一個 API 架構,用來保護、增強和控制對於 API 服務的訪問。

API 網關是一個處於應用程序或服務(提供 REST API 接口服務)之前的系統,用來管理授權、訪問控制和流量限制等,這樣 REST API 接口服務就被 API 網關保護起來,對所有的調用者透明。因此,隱藏在 API 網關後面的業務系統就可以專註於創建和管理服務,而不用去處理這些策略性的基礎設施。

API 網關的職能

API 網關的分類與功能

2. Gateway是什麼

Spring Cloud Gateway是Spring官方基於Spring 5.0,Spring Boot 2.0和Project Reactor等技術開發的網關,Spring Cloud Gateway旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。Spring Cloud Gateway作為Spring Cloud生態系中的網關,目標是替代ZUUL,其不僅提供統一的路由方式,並且基於Filter鏈的方式提供瞭網關基本的功能,例如:安全,監控/埋點,和限流等。

3. 為什麼用Gateway

Spring Cloud Gateway 可以看做是一個 Zuul 1.x 的升級版和代替品,比 Zuul 2 更早的使用 Netty 實現異步 IO,從而實現瞭一個簡單、比 Zuul 1.x 更高效的、與 Spring Cloud 緊密配合的 API 網關。

Spring Cloud Gateway 裡明確的區分瞭 Router 和 Filter,並且一個很大的特點是內置瞭非常多的開箱即用功能,並且都可以通過 SpringBoot 配置或者手工編碼鏈式調用來使用。

比如內置瞭 10 種 Router,使得我們可以直接配置一下就可以隨心所欲的根據 Header、或者 Path、或者 Host、或者 Query 來做路由。

比如區分瞭一般的 Filter 和全局 Filter,內置瞭 20 種 Filter 和 9 種全局 Filter,也都可以直接用。當然自定義 Filter 也非常方便。

最重要的幾個概念

4. Gateway怎麼用

說白瞭 Predicate 就是為瞭實現一組匹配規則,方便讓請求過來找到對應的 Route 進行處理,接下來我們接下 Spring Cloud GateWay 內置幾種 Predicate 的使用。

通過時間匹配

Predicate 支持設置一個時間,在請求進行轉發的時候,可以通過判斷在這個時間之前或者之後進行轉發。比如我們現在設置隻有在 2019 年 1 月 1 日才會轉發到我的網站,在這之前不進行轉發,我就可以這樣配置:

spring:
  cloud:
    gateway:
      routes:
       - id: time_route
        uri: http://ityouknow.com
        predicates:
         - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

Spring 是通過 ZonedDateTime 來對時間進行的對比,ZonedDateTime 是 Java 8 中日期時間功能裡,用於表示帶時區的日期與時間信息的類,ZonedDateTime 支持通過時區來設置時間,中國的時區是:Asia/Shanghai

After Route Predicate 是指在這個時間之後的請求都轉發到目標地址。上面的示例是指,請求時間在 2018 年 1 月 20 日 6 點 6 分 6 秒之後的所有請求都轉發到地址http://ityouknow.com+08:00是指時間和 UTC 時間相差八個小時,時間地區為Asia/Shanghai

添加完路由規則之後,訪問地址http://localhost:8080會自動轉發到http://ityouknow.com

Before Route Predicate 剛好相反,在某個時間之前的請求的請求都進行轉發。我們把上面路由規則中的 After 改為 Before,如下:

spring:
  cloud:
    gateway:
      routes:
       - id: after_route
        uri: http://ityouknow.com
        predicates:
         - Before=2018-01-20T06:06:06+08:00[Asia/Shanghai]

就表示在這個時間之前可以進行路由,在這時間之後停止路由,修改完之後重啟項目再次訪問地址http://localhost:8080,頁面會報 404 沒有找到地址。

除過在時間之前或者之後外,Gateway 還支持限制路由請求在某一個時間段范圍內,可以使用 Between Route Predicate 來實現。

spring:
  cloud:
    gateway:
      routes:
       - id: after_route
        uri: http://ityouknow.com
        predicates:
         - Between=2018-01-20T06:06:06+08:00[Asia/Shanghai], 2019-01-20T06:06:06+08:00[Asia/Shanghai]

這樣設置就意味著在這個時間段內可以匹配到此路由,超過這個時間段范圍則不會進行匹配。通過時間匹配路由的功能很酷,可以用在限時搶購的一些場景中。

通過 Cookie 匹配

Cookie Route Predicate 可以接收兩個參數,一個是 Cookie name , 一個是正則表達式,路由規則會通過獲取對應的 Cookie name 值和正則表達式去匹配,如果匹配上就會執行路由,如果沒有匹配上則不執行。

spring:
  cloud:
    gateway:
      routes:
       - id: cookie_route
         uri: http://ityouknow.com
         predicates:
         - Cookie=ityouknow, kee.e

使用 curl 測試,命令行輸入:

curl http://localhost:8080 --cookie "ityouknow=kee.e"

則會返回頁面代碼,如果去掉--cookie "ityouknow=kee.e",後臺匯報 404 錯誤。

Header Route Predicate 和 Cookie Route Predicate 一樣,也是接收 2 個參數,一個 header 中屬性名稱和一個正則表達式,這個屬性值和正則表達式匹配則執行。

spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: http://ityouknow.com
        predicates:
        - Header=X-Request-Id, \d+

使用 curl 測試,命令行輸入:

curl http://localhost:8080  -H "X-Request-Id:666666" 

則返回頁面代碼證明匹配成功。將參數-H "X-Request-Id:666666"改為-H "X-Request-Id:neo"再次執行時返回 404 證明沒有匹配。

通過 Host 匹配

Host Route Predicate 接收一組參數,一組匹配的域名列表,這個模板是一個 ant 分隔的模板,用.號作為分隔符。它通過參數中的主機地址作為匹配規則。

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: http://ityouknow.com
        predicates:
        - Host=**.ityouknow.com

使用 curl 測試,命令行輸入:

curl http://localhost:8080  -H "Host: www.ityouknow.com" 
curl http://localhost:8080  -H "Host: md.ityouknow.com" 

經測試以上兩種 host 均可匹配到 host_route 路由,去掉 host 參數則會報 404 錯誤。

通過請求方式匹配

可以通過是 POST、GET、PUT、DELETE 等不同的請求方式來進行路由。

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: http://ityouknow.com
        predicates:
        - Method=GET

使用 curl 測試,命令行輸入:

# curl 默認是以 GET 的方式去請求
curl http://localhost:8080

測試返回頁面代碼,證明匹配到路由,我們再以 POST 的方式請求測試。

# curl 默認是以 GET 的方式去請求
curl -X POST http://localhost:8080

返回 404 沒有找到,證明沒有匹配上路由

通過請求路徑匹配

Path Route Predicate 接收一個匹配路徑的參數來判斷是否走路由。

spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: http://ityouknow.com
        predicates:
        - Path=/foo/{segment}

如果請求路徑符合要求,則此路由將匹配,例如:/foo/1 或者 /foo/bar。

使用 curl 測試,命令行輸入:

curl http://localhost:8080/foo/1
curl http://localhost:8080/foo/xx
curl http://localhost:8080/boo/xx

經過測試第一和第二條命令可以正常獲取到頁面返回值,最後一個命令報 404,證明路由是通過指定路由來匹配。

通過請求參數匹配

Query Route Predicate 支持傳入兩個參數,一個是屬性名一個為屬性值,屬性值可以是正則表達式。

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: http://ityouknow.com
        predicates:
        - Query=smile

這樣配置,隻要請求中包含 smile 屬性的參數即可匹配路由。

使用 curl 測試,命令行輸入:

curl localhost:8080?smile=x&id=2

經過測試發現隻要請求匯總帶有 smile 參數即會匹配路由,不帶 smile 參數則不會匹配。

還可以將 Query 的值以鍵值對的方式進行配置,這樣在請求過來時會對屬性值和正則進行匹配,匹配上才會走路由。

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: http://ityouknow.com
        predicates:
        - Query=keep, pu.

這樣隻要當請求中包含 keep 屬性並且參數值是以 pu 開頭的長度為三位的字符串才會進行匹配和路由。

使用 curl 測試,命令行輸入:

curl localhost:8080?keep=pub

測試可以返回頁面代碼,將 keep 的屬性值改為 pubx 再次訪問就會報 404, 證明路由需要匹配正則表達式才會進行路由。

通過請求 ip 地址進行匹配

Predicate 也支持通過設置某個 ip 區間號段的請求才會路由,RemoteAddr Route Predicate 接受 cidr 符號 (IPv4 或 IPv6) 字符串的列表(最小大小為 1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子網掩碼)。

spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: http://ityouknow.com
        predicates:
        - RemoteAddr=192.168.1.1/24

可以將此地址設置為本機的 ip 地址進行測試。

果請求的遠程地址是 192.168.1.10,則此路由將匹配。

組合使用

上面為瞭演示各個 Predicate 的使用,我們是單個單個進行配置測試,其實可以將各種 Predicate 組合起來一起使用。

例如:

spring:
  cloud:
    gateway:
      routes:
       - id: host_foo_path_headers_to_httpbin
        uri: http://ityouknow.com
        predicates:
        - Host=**.foo.org
        - Path=/headers
        - Method=GET
        - Header=X-Request-Id, \d+
        - Query=foo, ba.
        - Query=baz
        - Cookie=chocolate, ch.p
        - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]

各種 Predicates 同時存在於同一個路由時,請求必須同時滿足所有的條件才被這個路由匹配。

一個請求滿足多個路由的謂詞條件時,請求隻會被首個成功匹配的路由轉發

到此這篇關於Gateway網關工作原理及使用方法的文章就介紹到這瞭。希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: