Spring Cloud: API網關 Gateway

網關的作用

在微服務架構下,單體應用被分割成多個微服務,如果將所有的微服務直接對外暴露,會出現一些安全問題,全部做鑑權處理的話,不光效率底下,而且管理起來更是複雜,而且有一些服務協議不是Web友好的協議。

爲了解決上述問題,出現了使用API網管的解決方案。API網關自身也是一個服務,並且是後端服務的唯一入口。從面向對象設計的角度看,它與外觀模式類似。API網關封裝了系統內部架構,爲每個客戶端提供一個定製的API。除此之外,它還可以負責身份驗證、監控、負載均衡、限流、降級與應用檢測等功能。

Spring Cloud Gateway 簡介

Spring Cloud Gateway是Spring官方基於Spring 5.0、Spring Boot 2.0和ProjectReactor等技術開發的網關,Spring Cloud Gateway旨在爲微服務架構提供簡單、有效且統一的API路由管理方式。Spring Cloud Gateway作爲Spring Cloud生態系中的網關

Spring Cloud Gateway依賴Spring Boot和Spring WebFlux,基於Netty運行。它不能在傳統的servlet容器中工作,也不能構建成war包。

Gateway中最重要的幾個概念:

  • 路由(route):路由是網關最基礎的部分,路由信息由一個ID、一個目的url、一組斷言工廠和一組Filter組成。如果路由斷言爲真,則說明請求的url和配置的路由匹配。
  • 斷言(Predicate)。Java 8中的斷言函數。Spring Cloud Gateway中的斷言函數輸入類型是Spring 5.0框架中的ServerWebExchange。Spring CloudGateway中的斷言函數允許開發者去定義匹配來自於Http Request中的任何信息,比如請求頭和參數等。
  • 過濾器(filter)。一個標準的Spring webFilter。Spring Cloud Gateway中的Filter分爲兩種類型的Filter,分別是Gateway Filter和Global Filter。過濾器Filter將會對請求和響應進行修改處理。

基礎應用

創建一個新的consul-gateway用作API網關,和之前的consul-consumer作爲服務,服務註冊到了Consul上,通過請求網管獲取服務

Consul的使用和consul-consumer的創建可以看之前文章:Spring Cloud: 註冊中心Consul使用
在這裏插入圖片描述

1. 新建一個項目consul-gateway

依賴如下, 添加consul-config作爲配置中心:

    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway:2.2.2.RELEASE'
    implementation 'org.springframework.cloud:spring-cloud-starter-consul-discovery:2.2.2.RELEASE'
    implementation 'org.springframework.cloud:spring-cloud-starter-consul-config:2.2.2.RELEASE'

pswebgateway使WebFlux\color{red}{ps:注意不要添加web依賴,因爲gateway使用的是WebFlux}

編寫配置文件, bootstrap.yml:

spring:
  application:
    name: consul-gateway
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        prefer-ip-address: true
        service-name: ${spring.application.name}
      config:
        format: yaml    # 配置各式yaml或properties
        profile-separator: ':'   # 配置分隔符,默認爲“,”

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
       

啓動類不需要修改。

在這裏插入圖片描述

成功添加到註冊中心。

Gateway的各種網管功能配置用起來很舒服,故意避開了代碼編寫,可以直接通過配置文件進行編寫,這樣的話只要維護修改配置文件就可以更改網管的路由篩選邏輯,配置文件再通過配置中心統一管理,邏輯更加方便維護管理。

2. 配置文件

application. yml:

server:
  port: 8730

spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: http://localhost:8710
        predicates:
          - Path=/feign

      - id: path_route
        uri: https://blog.csdn.net
        predicates:
          - Path=/tonydz0523/**

這裏直接在配置文件中編寫路由邏輯:

  - id: path_route
    uri: http://localhost:8710
    predicates:
      - Path=/feign
  • http://localhost:8710是consumer的地址
  • - Path=/feign是可以跳轉的路徑
  • 當你訪問 http://localhost:8730/feign就會跳轉到http://localhost:8710/feign

在這裏插入圖片描述

如果需要支持多級Path的話只要加上**即可:

      - id: path_route
        uri: https://blog.csdn.net
        predicates:
          - Path=/tonydz0523/**

訪問http://localhost:8730/tonydz0523/article/details/106551483就會跳轉到http://blog.csdn.net/tonydz0523/article/details/106551483

在這裏插入圖片描述

3. 獲取Consul註冊服務

首先要先開啓locator功能:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true

然後添加route規則:

      - id: consul-consumer
        uri: lb://consul-consumer
        predicates:
          - Path=/consul-consumer/**

uri以lb://開頭(lb代表從註冊中心獲取服務),後面接的就是你需要轉發到的服務名稱,這個服務名稱必須跟Consul中的對應,否則會找不到服務

通過訪問http://localhost:8730/consul-consumer/feign即可通過consul註冊中心跳轉到consul-consumer服務:

在這裏插入圖片描述

由於我註冊在Consul上的兩個consul-consumer其中又一個沒有寫feign路徑的服務,因此一個訪問沒有結果。

Gateway路由斷言工廠

After路由斷言

在設置的After時間之後可以進行轉發,否者不可以

      - id: after_route
        uri: https://example.org
        predicates:
        - After=2020-06-06T16:32:12.975035+08:00[Asia/Shanghai]

時間可以ZonedDateTime通過獲得:

ZonedDateTime.now().format(DateTimeFormatter.ISO_ZONED_DATE_TIME);

Before路由斷言

在設置的Before時間之後可以進行轉發,否者不可以

      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2020-06-06T16:32:12.975035+08:00[Asia/Shanghai]

Between路由斷言

設置一個時間段,訪問時間在這個時間段的話可以跳轉,兩個時間通過隔開

      - id: between_route
        uri: https://example.org
        predicates:
        - Between=2020-06-06T16:32:12.975035+08:00[Asia/Shanghai],2020-06-07T16:32:12.975035+08:00[Asia/Shanghai]

Cookie路由斷言

cookie名稱對應的key和value。當請求中攜帶的cookie和Cookied斷言工廠中配置的cookie一致,則路由匹配成功,否則匹配不成功;key和value通過隔開,value位置可以是正則表達式用來匹配value

      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

Header路由斷言

Header路由斷言工廠用於根據配置的路由header信息進行斷言匹配路由,匹配成功進行轉發,否則不進行轉發。key和value通過通過隔開,value位置可以是正則表達式用來匹配value

      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

Host路由斷言

Host路由斷言工廠根據配置的Host,對請求中的Host進行斷言處理,斷言成功則進行路由轉發,否則不轉發。可以使用**模糊匹配,而且添加多個通過隔開

      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

Method路由斷言

Method路由斷言工廠會根據路由信息配置的method對請求方法是Get或者Post等進行斷言匹配

      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

只有GET和POST請求可以轉發

Path路由斷言

Path路由斷言工廠接收一個參數,根據Path定義好的規則來判斷訪問的URI是否匹配

      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment},/yellow/**

如果請求路徑爲/red/xxx可以通過匹配,也可以使用正則進行匹配,如/yellow/**

Query路由斷言

Query路由斷言工廠會從請求中獲取兩個參數,將請求中參數和Query斷言路由中的配置進行匹配,一致則轉發成功,否則轉發失敗

      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green, re.

兩個參數一個必需的參數和一個可選的正則表達式, https://example.org?green=rex可以匹配

RemoteAddr路由斷言

RemoteAddr路由斷言工廠配置一個IPv4或IPv6網段的字符串或者IP。當請求IP地址在網段之內或者和配置的IP相同,則表示匹配成功,成功轉發,否則不能轉發。例如192.1680.1/16是一個網段,其中192.168.0.1是IP地址,16是子網掩碼,當然也可以直接配置一個IP。

      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1

Weight路由斷言

Weight路由斷言工程接收兩個參數:groupweight。通過group將多個uri分爲一組,weight則是權重值

      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
        - Weight=group1, 2

route會將約80%的流量轉發至weighthigh.org,並將約20%的流量轉發至weightlow.org。

Gateway內置的Filter

Spring Cloud Gatewat中內置很多的路由過濾工廠,當然可以自己根據實際應用場景需要定製的自己的路由過濾器工廠。路由過濾器允許以某種方式修改請求進來的http請求或返回的http響應。路由過濾器主要作用於需要處理的特定路由。SpringCloud Gateway提供了很多種類的過濾器工廠,過濾器的實現30多個。總得來說,可以分爲七類:Header、Parameter、Path、Status、Redirect跳轉、Hytrix熔斷和RateLimiter

介紹幾種常用的:

AddRequestHeader過濾器

通過名稱我們可以快速明白這個過濾器工廠的作用是添加請求頭。

      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue
        
      - id: add_request_header_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - AddRequestHeader=X-Request-Red, Blue-{segment}

符合規則匹配成功的請求,將添加X-Request-red:blue請求頭,將其傳遞到後端服務中,後方服務可以直接獲取請求頭信息。URI變量中的值,可以應用到header中

AddRequestParameter過濾器

AddRequestParameter過濾器作用是對匹配上的請求路由添加請求參數,添加的是一對key和value

      - id: add_request_parameter_route
        uri: https://example.org
        filters:
        - AddRequestParameter=red, blue

添加訪問參數red=blue

RemoveRequestHeader過濾器

RemoveRequestHeader是移除請求頭的過濾器工廠,可以在請求轉發到後端服務之前進行Header的移除操作。與上面相反是將減少請求頭

      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveRequestHeader=X-Request-Foo

SetStatus過濾器

SetStatus過濾器工廠接收單個狀態,用於設置Http請求的響應碼。它必須是有效的Spring Httpstatus(org.springframework.http.HttpStatus)。它可以是整數值404或枚舉類型NOT_FOUND。

      - id: setstatusstring_route
        uri: https://example.org
        filters:
        - SetStatus=BAD_REQUEST
      - id: setstatusint_route
        uri: https://example.org
        filters:
        - SetStatus=401

可以通過如下設置以從代理請求返回原始HTTP狀態代碼:

spring:
  cloud:
    gateway:
      set-status:
        original-status-header-name: original-http-status

RewritePath過濾器

這使用Java正則表達式提供了一種靈活的方式來重寫請求路徑,兩個參數,前面用來匹配原來路徑,後面是新生成路徑

      - id: rewritepath_route
        uri: https://example.org
        predicates:
        - Path=/red/**
        filters:
        - RewritePath=/red(?<segment>/?.*), $\{segment}

StripPrefix過濾器

StripPrefixGatewayFilterFactory是一個對針對請求url前綴進行處理的filter工廠,用於去除前綴。而PrefixPathGatewayFilterFactory是用於增加前綴。

      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2

用於減少前綴,如https://blog.csdn.net/tonydz0523/article/details/106551483減少兩個前綴->https://blog.csdn.net/details/106551483

RedirectTo過濾器

用於重定向操作,工廠有兩個參數,statusurl。該status參數應該是300系列重定向HTTP代碼,例如301。該url參數應該是有效的URL。

      - id: prefixpath_route
        uri: https://example.org
        filters:
        - RedirectTo=302, https://acme.org

Retry過濾器

網關作爲所有請求流量的入口,網關對路由進行協議適配和協議轉發處理的過程中,如果出現異常或網絡抖動,爲了保證後端服務請求的高可用,一般處理方式會對網絡請求進行重試,Retry過濾器包含如下參數:

  • retries:應嘗試的重試次數。
  • statuses:應重試的HTTP狀態代碼,以表示org.springframework.http.HttpStatus
  • methods:應該重試的HTTP方法,以表示org.springframework.http.HttpMethod
  • series:可以retry的狀態,使用表示org.springframework.http.HttpStatus.Series
  • exceptions:可以激活retry的異常列表。
  • backoff:爲重試配置的指數補償。重試在的間隔後執行firstBackoff * (factor ^ n),其中n爲迭代。如果maxBackoff已配置,則應用的最大退避限制爲maxBackoff。如果basedOnPreviousValue爲true,則使用prevBackoff * factor計算間隔。

默認配置如下:

  • retries:3次
  • series:5XX系列
  • methods:GET方法
  • exceptionsIOExceptionTimeoutException
  • backoff:禁用
      - id: retry_test
        uri: http://localhost:8080/flakey
        predicates:
        - Host=*.retry.com
        filters:
        - name: Retry
          args:
            retries: 3
            statuses: BAD_GATEWAY
            methods: GET,POST
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

Hystrix過濾器

Hystrix的相關內容,請看之前文章:SpringCloud: 熔斷器Hystrix 、Turbine (多圖)

需要一個name參數,它是的名稱HystrixCommand

      - id: hystrix_route
        uri: https://example.org
        filters:
        - Hystrix=myCommandName

Hystrix過濾器還可以接受可選fallbackUri參數

      - id: hystrix_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/consumingserviceendpoint
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/incaseoffailureusethis
        - RewritePath=/consumingserviceendpoint, /backingserviceendpoint

默認過濾器

要添加過濾器並將其應用於所有路由,可以使用spring.cloud.gateway.default-filters。此屬性採用過濾器列表

spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin

Cors配置

您可以配置網關以控制CORS行爲。“全局” CORS配置是URL模式到CorsConfiguration的映射。以下示例配置了CORS:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://docs.spring.io"
            allowedMethods:
            - GET

RequestRateLimiter

待補充

GlobalFilter

待補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章