1. 程式人生 > 其它 >SpringCloud:閘道器getway 路由轉發

SpringCloud:閘道器getway 路由轉發

Spring Cloud Gateway 是 Spring Cloud 的一個全新專案,該專案是基於 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的閘道器,它旨在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。

Spring Cloud Gateway 作為 Spring Cloud 生態系統中的閘道器,目標是替代 Netflix Zuul,其不僅提供統一的路由方式,並且基於 Filter 鏈的方式提供了閘道器基本的功能,例如:安全,監控/指標,和限流。

相關概念:

Route(路由):這是閘道器的基本構建塊。它由一個 ID,一個目標 URI,一組斷言和一組過濾器定義。如果斷言為真,則路由匹配。

Predicate(斷言):這是一個 Java 8 的 Predicate。輸入型別是一個 ServerWebExchange。我們可以使用它來匹配來自 HTTP 請求的任何內容,例如 headers 或引數。
Filter(過濾器):這是org.springframework.cloud.gateway.filter.GatewayFilter的例項,我們可以使用它修改請求和響應。

快速上手

新增專案需要使用的依賴包

    <dependency>
            <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--將微服務provider註冊進eureka --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</
artifactId
>
</dependency>

啟動類

@EnableDiscoveryClient
@SpringBootApplication
public class GetwayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GetwayApplication.class, args);
    }

}

先來測試一個最簡單的請求轉發。

server:
  port: 8080
spring:
  cloud:
    gateway:
      routes:
      - id: neo_route
        uri: http://www.baidu.com
        predicates:
        - Path=/spring-cloud

訪問http://localhost:8080/spring-cloud 即轉發到百度http://www.baidu.com/spring-cloud

動態路由伺服器名轉發

server:

  port: 9999
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          # 開啟後只要註冊過的服務可以通過服務名轉發(服務名稱小寫,無需配置路由)
          # 閘道器地址/服務名稱/方法 如(http://localhost:9999/producter-service/producter/list)
          enabled: true
          lower-case-service-id: true #服務名小寫

在這裡插入圖片描述
http://localhost:9999/producter-service/producter/list
可以訪問註冊在eurake上的producter-service的producter/list方法

幾種匹配規則

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 屬性匹配
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 地址進行測試。

curl localhost:8080
果請求的遠端地址是 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 同時存在於同一個路由時,請求必須同時滿足所有的條件才被這個路由匹配。

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