Spring Cloud Gateway 之 Predict

Spring Cloud gateway工做流程

在以前的文章的Spring Cloud Gateway初體驗中,你們已經對Spring Cloud Gateway的功能有一個初步的認識,網關做爲一個系統的流量的入口,有着舉足輕重的做用,一般的做用以下:前端

  • 協議轉換,路由轉發
  • 流量聚合,對流量進行監控,日誌輸出
  • 做爲整個系統的前端工程,對流量進行控制,有限流的做用
  • 做爲系統的前端邊界,外部流量只能經過網關才能訪問系統
  • 能夠在網關層作權限的判斷
  • 能夠在網關層作緩存

Spring Cloud Gateway做爲Spring Cloud框架的第二代網關,在功能上要比Zuul更加的強大,性能也更好。隨着Spring Cloud的版本迭代,Spring Cloud官方有打算棄用Zuul的意思。在筆者調用了Spring Cloud Gateway的使用和功能上,Spring Cloud Gateway替換掉Zuul的成本上是很是低的,幾乎能夠無縫切換。Spring Cloud Gateway幾乎包含了zuul的全部功能。git

Spring Cloud Gateway 之 Predict

如上圖所示,客戶端向Spring Cloud Gateway發出請求。 若是Gateway Handler Mapping肯定請求與路由匹配(這個時候就用到predicate),則將其發送到Gateway web handler處理。 Gateway web handler處理請求時會通過一系列的過濾器鏈。 過濾器鏈被虛線劃分的緣由是過濾器鏈能夠在發送代理請求以前或以後執行過濾邏輯。 先執行全部「pre」過濾器邏輯,而後進行代理請求。 在發出代理請求以後,收到代理服務的響應以後執行「post」過濾器邏輯。這跟zuul的處理過程很相似。在執行全部「pre」過濾器邏輯時,每每進行了鑑權、限流、日誌輸出等功能,以及請求頭的更改、協議的轉換;轉發以後收到響應以後,會執行全部「post」過濾器的邏輯,在這裏能夠響應數據進行了修改,好比響應頭、協議的轉換等。程序員

在上面的處理過程當中,有一個重要的點就是講請求和路由進行匹配,這時候就須要用到predicate,它是決定了一個請求走哪個路由。github

Predicate 介紹

Predicate 來源於 Java 8,是 Java 8 中引入的一個函數,Predicate 接受一個輸入參數,返回一個布爾值結果。該接口包含多種默認方法來將 Predicate 組合成其餘複雜的邏輯(好比:與,或,非)。能夠用於接口請求參數校驗、判斷新老數據是否有變化須要進行更新操做。web

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性實現了各類路由匹配規則,有經過 Header、請求參數等不一樣的條件來進行做爲條件匹配到對應的路由。網上有一張圖總結了 Spring Cloud 內置的幾種 Predicate 的實現。正則表達式

Spring Cloud Gateway 之 Predict

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

Predicate 實戰

經過時間匹配

Predicate 支持設置一個時間,在請求進行轉發的時候,能夠經過判斷在這個時間以前或者以後進行轉發。好比咱們如今設置只有在2019年2月15日纔會轉發到個人簡書地址,在這以前不進行轉發,我就能夠這樣配置:shell

spring:
  cloud:
    gateway:
      routes:
        - id: after_route
          uri: http://httpbin.org
          predicates:
          - After=2018-02-15T00:00:00+08:00[Asia/Shanghai]

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

After Route Predicate 是指在這個時間以後的請求都轉發到目標地址。上面的示例是指,請求時間在 2019年2月15日0點0分0秒以後的全部請求都轉發到地址http://httpbin.org。+08:00是指時間和UTC時間相差八個小時,時間地區爲Asia/Shanghaimarkdown

添加完路由規則以後,訪問地址 http://127.0.0.1:8080/get 會自動轉發到 http://httpbin.org/get

Before Route Predicate 恰好相反,在某個時間以前的請求的請求都進行轉發。咱們把上面路由規則中的 After 改成 Before,以下:

spring:
  cloud:
    gateway:
      routes:
        - id: before_route
          uri: http://httpbin.org
          predicates:
          - Before=2019-02-15T00:00:00+08:00[Asia/Shanghai]

就表示在2019-02-14以前能夠進行路由,在這時間以後中止路由,修改完以後重啓項目再次訪問地址http://localhost:8080,頁面會報 404 沒有找到地址。

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

spring:
  cloud:
    gateway:
      routes:
        - id: between_route
          uri: http://httpbin.org
          predicates:
          - Between=2018-02-14T00:00:00+08:00[Asia/Shanghai], 2019-02-16T23:59:59+08:00[Asia/Shanghai]

這樣設置就意味着在 2019-02-14到2019-02-16 時間段內能夠匹配到此路由,超過這個時間段範圍則不會進行匹配。經過時間匹配路由的功能很酷,能夠用在限時搶購的一些場景中。

經過 Cookie 匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: cookie_route
          uri: http://httpbin.org:80
          predicates:
          - Cookie=name, chengxuyuanguoguo

上面的配置中,請求帶有cookie名爲name, cookie值爲chengxuyuanguoguo 的請求將都會轉發到uri爲 http://httpbin.org的地址上

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

curl http://127.0.0.1:8080/get --cookie "name=chengxuyuanguoguo"

則有正確返回,若是去掉--cookie "name=chengxuyuanguoguo",沒有匹配成功,出現 404 錯誤。

經過 Header 屬性匹配

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

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

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

curl http://127.0.0.1:8080/get  -H "X-Request-Id:111111"

則正常返回,將參數 "X-Request-Id:111111" 改成 "X-Request-Id:xxxx" 再次執行時返回404。

經過 Host 匹配

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

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

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

curl http://127.0.0.1:8080/get  -H "Host:www.httpbin.com"

測試上述 host 可匹配到 host_route 路由,去掉 host 參數則會報 404 錯誤。

經過請求方式匹配

能夠經過是 POST、GET、PUT、DELETE 等不一樣的請求方式來進行路由。

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

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

curl http://127.0.0.1:8080/get

測試返回正確,證實匹配到路由,再以 POST 的方式請求測試:

curl -X POST http://127.0.0.1:8080/get

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

經過請求路徑匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://httpbin.org
          predicates:
            - Path=/foo/{segment}

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

curl http://127.0.0.1:8080/foo/1
curl http://127.0.0.1:8080/fee/1

測試第一命令能夠正常獲取到頁面返回值,第二個命令報404,證實路由是經過指定路由來匹配。

經過請求參數匹配

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

spring:
  cloud:
    gateway:
      routes:
        - id: query_route
          uri: http://httpbin.org
          predicates:
          - Query=foo

測試發現只要請求帶有 foo 參數即會匹配路由,不帶 foo 參數則會報 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://httpbin.org
          predicates:
          - RemoteAddr=172.16.1.73/24

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

curl http://172.17.1.73:8080/get

測試返回正確,改成請求 127.0.0.1:8080/get 則會報 404 錯誤。

組合使用

Predicate還能夠組合在一塊兒使用。

spring:
  cloud:
    gateway:
      routes:
        - id: group_route
          uri: http://httpbin.org
          predicates:
          - Host=**.httpbin.com
          - Header=X-Request-Id, \d+
          - Cookie=name, chengxuyuanguoguo
          - After=2019-02-15T00:00:00+08:00[Asia/Shanghai]

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

curl http://127.0.0.1:8080 -H "X-Request-Id:111111" -H "Host:www.httpbin.com" --cookie "name=chengxuyuanguoguo"

測試返回正確,錯誤的規則或去除一個規則,則會報 404 錯誤。

總結

Predict做爲斷言,它決定了請求會被路由到哪一個router 中。在斷言以後,請求會被進入到filter過濾器的邏輯,下篇文章將會介紹Spring Cloud Gateway過濾器相關的內容。

源碼:https://github.com/gf-huanchupk/SpringCloudLearning/tree/master/chapter13/springcloud-gateway-predict

歡迎關注個人公衆號《程序員果果》,關注有驚喜~~
Spring Cloud Gateway 之 Predict

相關文章
相關標籤/搜索