Spring Cloud GateWay 路由轉發規則介紹

Spring在因Netflix開源流產事件後,在不斷的更換Netflix相關的組件,好比:EurekaZuulFeignRibbon等,Zuul的替代產品就是SpringCloud Gateway,這是Spring團隊研發的網關組件,能夠實現限流、安全認證、支持長鏈接等新特性。html

Spring Cloud Gateway

Spring Cloud GatewaySpringCloud的全新子項目,該項目基於Spring5.xSpringBoot2.x技術版本進行編寫,意在提供簡單方便、可擴展的統一API路由管理方式。
概念解釋:java

  • Route(路由):路由是網關的基本單元,由ID、URI、一組Predicate、一組Filter組成,根據Predicate進行匹配轉發。
  • Predicate(謂語、斷言):路由轉發的判斷條件,目前SpringCloud Gateway支持多種方式,常見如:PathQueryMethodHeader等。
  • Filter(過濾器):過濾器是路由轉發請求時所通過的過濾邏輯,可用於修改請求、響應內容。

Spring Cloud GateWay 工做流程以下所示
spring-cloud-gateway-work.pnggit

客戶端向Spring Cloud Gateway發出請求。若是網關處理程序映射肯定請求與路由匹配,則將其發送到網關Web處理程序。此處理程序運行時經過特定於請求的篩選鏈發送請求。過濾器被虛線分隔的緣由是過濾器能夠在發送代理請求以前或以後執行邏輯。執行全部「預」過濾邏輯,而後發出代理請求。在發出代理請求後,將執行「post」過濾器邏輯。spring

開始使用

Spring Cloud Gateway目前有兩種方式進行配置:api

  • application.yml配置文件方式
  • 經過@Bean註解RouteLocator方法返回值

在本章會側重針對配置文件方式進行講解,固然RouteLocator方式也會簡單的告訴你們的使用方式。安全

添加依賴

添加Spring Cloud Gateway相關依賴,pom.xml以下所示:cookie

//...省略部份內容
<properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <!--Spring Cloud Gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
//...省略部份內容

Spring Cloud Gateway Predicates

在咱們開始本章內容以前咱們要來先了解下Spring Cloud Gateway內部提供的全部謂語、斷言,這樣咱們才能目標性的進行學習,我整理出來了一個腦圖,以下所示:app

SpringCloud-Gateway-Predicates.png

每個Predicate的使用,你能夠理解爲:當知足這種條件後纔會被轉發,若是是多個,那就是都知足的狀況下被轉發。curl

Path 方式匹配轉發

經過Path轉發示例,咱們講解下上面的兩種配置,分別是application.yml以及RouteLocatorspring-boot

配置文件匹配地址轉發

咱們在application.yml配置文件內添加對應的路由配置,以下所示:

spring:
  application:
    name: spring-cloud-gateway-sample
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            # 匹配路徑轉發
            - Path=/api-boot-datasource-switch.html
# 端口號
server:
  port: 9090

先來解釋下route的組成部分:

  • id:路由的ID
  • uri:匹配路由的轉發地址
  • predicates:配置該路由的斷言,經過PredicateDefinition類進行接收配置。

在上面的配置中,當訪問http://localhost:9090/api-boot-datasource-switch.html時就會被自動轉發到http://blog.yuqiyu.com/api-boot-datasource-switch.html,這裏要注意徹底匹配Path的值時纔會進行路由轉發。

訪問效果以下所示:

spring-cloud-gateway-path-predicate.png

RouteLocator 匹配路徑轉發

在上面的配置中,若是使用RouteLocator方式該怎麼進行配置呢?

以下所示:

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
  return builder.routes()
    .route("blog", r -> 
           r.path("/api-boot-datasource-switch.html").uri("http://blog.yuqiyu.com"))
    .build();
}

Before 方式匹配轉發

當部署有訪問時間限制的接口時,咱們能夠經過Before Predicate來完成某一個時間點以前容許訪問,過期後則不容許轉發請求到具體的服務,配置以下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Before=2019-05-01T00:00:00+08:00[Asia/Shanghai]

在上面配置中,咱們容許2019-05-01日凌晨以前經過路由轉發到http://blog.yuqiyu.com,經過查看org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory源碼咱們發現,Spring Cloud GatewayBefore斷言採用的ZonedDateTime進行匹配時間,這裏要注意存在時區的問題,須要配置[Asia/Shanghai]做爲中國時區。

After 方式匹配轉發

After PredicateBefore配置使用一致,匹配某一個時間點以後容許路由轉發,以下所示配置:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - After=2019-04-29T00:00:00+08:00[Asia/Shanghai]

在上面配置中容許2019-04-29凌晨以後進行轉發到http://blog.yuqiyu.com

Between 方式匹配轉發

那若是是一個時間段內容許請求轉發,經過BeforeAfter組合配置也能夠完成,不過Spring Cloud Gateway仍是提供了Between方式,以下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Between=2019-04-29T00:00:00+08:00[Asia/Shanghai], 2019-05-01T00:00:00+08:00[Asia/Shanghai]

在上面配置中,容許在2019-04-29日凌晨後 & 2019-05-01凌晨以前請求轉發到http://blog.yuqiyu.com

Cookie 方式匹配轉發

Spring Cloud Gateway 還提供了根據Cookie值的方式匹配轉發請求,若是請求中所攜帶的Cookie值與配置的Predicate匹配,那麼就能夠被容許轉發到指定地址,以下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Cookie=hengboy, yuqiyu

在上面配置中,若是客戶端發送請求時攜帶了"hengboy=yuqiyu"的Cookie信息,則容許請求轉發。

測試Cookie方式轉發:

curl http://localhost:9090 --cookie "hengboy=yuqiyu"

經過上面方式咱們是能夠成功轉發請求的,若是咱們修改Cookie的值,就會致使沒法轉發,出現404。

Header 方式匹配轉發

Spring Cloud Gateway能夠根據發送請求的Header信息進行匹配轉發,加入咱們能夠根據X-Request-Id的值進行匹配,以下所示:

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

在上面配置中,若是X-Request-Id的值爲數字,那麼就能夠轉發到http://blog.yuqiyu.com,咱們經過以下方式進行測試:

curl http://localhost:9090 -H "X-Request-Id:123456"

若是頭信息爲X-Request-Id:abc時,就會轉發失敗,出現404。

Host 方式匹配轉發

Spring Cloud Gateway能夠根據Host主機名進行匹配轉發,若是咱們的接口只容許**.yuqiyu.com域名進行訪問,那麼配置以下所示:

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

測試以下所示:

1. curl http://localhost:9090 -H "Host: yuqiyu.com"          // 匹配
 2. curl http://localhost:9090 -H "Host: api.yuqiyu.com"        // 匹配
 3. curl http://localhost:9090 -H "Host: admin.yuqiyu.com"  // 匹配
 3. curl http://localhost:9090 -H "Host: hengboy.com"          // 不匹配

請求方式 方式匹配轉發

Rest請求風格的接口內每每會存在多種請求方式的接口,若是咱們的接口只容許POST請求訪問,那麼配置以下所示:

spring:
  cloud:
    gateway:
      routes:
        - id: blog
          uri: http://blog.yuqiyu.com
          predicates:
            - Method=POST

發送GET請求測試:

~ curl http://localhost:9090
{"timestamp":"2019-04-29T06:27:41.121+0000","path":"/","status":404,"error":"Not Found","message":null}

咱們的請求並未被Spring Cloud Gateway進行轉發,那麼咱們再來經過POST請求進行測試:

curl -X POST http://localhost:9090

是能夠被轉發到目標地址uri的,不過個人這個博客是OSS部署的,阿里雲限制了POST訪問,儘管如此咱們也證實了能夠轉發。

請求參數 方式匹配轉發

Spring Cloud GateWay還支持根據指定的參數進行匹配,Query方式的Predicate也有兩種方式匹配狀況,以下所示:

  • 請求中存在xxx參數

    spring:
      cloud:
        gateway:
          routes:
            - id: blog
              uri: http://blog.yuqiyu.com
              predicates:
咱們經過`curl http://localhost:9090\?xxx\=123`是能夠被成功轉發的,只要參數存在`xxx`就會被成功轉發,不然出現404轉發失敗。

- 請求中存在`xxx`參數且值爲`zzz`

spring:

cloud:
  gateway:
    routes:
      - id: blog
        uri: http://blog.yuqiyu.com
        predicates:
          - Query=xxx, zzz
根據上面配置,咱們限定了參數`xxx`必須爲`zzz`時纔會被成功轉發,不然一樣會出現404抓發失敗。

### 請求路徑 方式匹配轉發

`Spring Cloud Gateway`提供了請求路徑變量方式匹配轉發,以下所示:

spring:
cloud:

gateway:
  routes:
    - id: blog
      uri: http://blog.yuqiyu.com
      predicates:
        - Path=/article/{articleId}
在上面配置中`{articleId}`是一個路徑變量,能夠是任意值,匹配`/article/1`、`/article/abc`等,測試以下所示:

~ curl http://localhost:9090/article/1 // 匹配
~ curl http://localhost:9090/article/abc // 匹配
~ curl http://localhost:9090/article/1/1 // 不匹配

### 請求IP 方式匹配轉發

`Spring Cloud Gateway`能夠限制容許訪問接口的客戶端`IP`地址,配置後只對指定`IP`地址的客戶端進行請求轉發,配置以下所示:

spring:
cloud:

gateway:
  routes:
    - id: blog
      uri: http://blog.yuqiyu.com
      predicates:
        - RemoteAddr=192.168.1.56/24
在上面咱們配置了`192.168.1.56/24`,其中`192.168.1.56`是客戶端的`IP`地址,而`24`則是子網掩碼。

### 組合示例

相同的`Predicate`也能夠配置多個,請求的轉發是必須知足全部的`Predicate`後才能夠進行路由轉發,組合使用示例以下所示:

spring:
cloud:

gateway:
  routes:
    - id: blog
      uri: http://blog.yuqiyu.com
      predicates:
        - Query=author, hengboy
        - Query=yuqiyu
        - Method=GET
        - Cookie=hengboy, yuqiyu
        - Header=X-Request-Id, \d+
        - RemoteAddr=192.168.1.56/24
## 總結

本章節講解了`Spring Cloud Gateway`的相關`謂詞、斷言`基本使用方式,`GateWay`內部提供了不少種靈活的路由轉發規則,在同一個路由內存在多個`Predicate`時,同時知足規則後請求才會被路由轉發。



## 源碼位置

`Gitee`:<https://gitee.com/hengboy/spring-cloud-chapter/tree/master/SpringCloud/spring-cloud-gateway>
相關文章
相關標籤/搜索