Spring Cloud Gateway Route Predicate Factory 的使用

一、需求

記錄Spring Cloud Gateway的一些用法,不對其原理進行過多的探究。

二、基本組成

1、簡介

Spring Cloud Gateway 是 基于Spring boot 5、Spring Boot 2.0Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān)。它旨在為微服務(wù)提供一個簡單有效的方式來管理api路由。

Spring Cloud Gateway 是基于 Netty 運行的,不能運行在傳統(tǒng)的Servlet容器中作為War包運行。

2、核型概念

1、Route 路由

Route是網(wǎng)關(guān)的基本組成單元,它是有一個ID,一個目標(biāo)URI和一組predicates和一組filters組成,如果一組斷言結(jié)果為真,則匹配路由,目標(biāo)URI會被訪問。
注意:
1、多個 Predicate 之間是 邏輯and 的關(guān)系。
2、多個Predicate是從定義的順序從上到下依次執(zhí)行,也可以指定 order 屬性的值。

2、Predicate 謂語、斷言

Predicate 是Java 8 Function interface。輸入類型是Spring Framework ServerWebExchange??梢杂脕砥ヅ?code>HTTP請求中的任何內(nèi)容,例如headers 或者 parameters

3、Filter 過濾器

FilterGatewayFilter的實例。通過Filter我們可以在請求發(fā)送或返回下游服務(wù)時 修改 請求響應(yīng)

3、工作原理

Spring Cloud Gateway的工作原理

上圖來自 Spring 官網(wǎng)。

三、網(wǎng)關(guān) Predicate配置方式

1、快捷配置方式(配置文件)

快捷方式是由過濾器是的名稱識別,后面緊跟=,在跟以逗號(,)分隔的參數(shù)值。

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - Cookie=mycookie,mycookievalue

上一個示例使用兩個參數(shù)定義了Cookie Route Predicate Factory,這兩個參數(shù)是cookie名稱,mycookie和與mycookievalue匹配的值

2、完全展開的參數(shù)(配置文件)

name:指定謂詞工廠的名字
args:指定對應(yīng)謂詞工廠中的參數(shù)對應(yīng)的值。

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - name: Cookie
          args:
            name: mycookie
            regexp: mycookievalue

這種方式配置和上面的快捷方式配置的是一個意思

3、上方2種方式配置和代碼對應(yīng)關(guān)系

上方2種方式配置和代碼對應(yīng)關(guān)系

4、uri 值的方式

1、以http開頭

當(dāng)匹配到這個路由后,會跳轉(zhuǎn)到這個地址。

2、以 lb 開頭

eg:
?????uri: lb://service-name
解釋:
lb:表示負(fù)載均衡的意思
service-name:值的是調(diào)用服務(wù)在注冊中心注冊的服務(wù)名。

四、Route Predicate Factories

Spring Cloud Gateway內(nèi)置了特別多的路由謂詞工廠,用來匹配http請求。當(dāng)多個一起使用時,是and的關(guān)系,即需要所有的謂詞工廠都匹配,才匹配這個路由。

1、After

1、描述:

當(dāng)前請求在指定時間之后才匹配

2、存在參數(shù):

????datetime 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - After=2020-11-01T11:05:08.020+08:00[Asia/Shanghai]

2、Before

1、描述:

當(dāng)前請求在指定時間之前才匹配

2、存在參數(shù):

????datetime 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Before=2020-11-01T11:05:08.020+08:00[Asia/Shanghai]

3、Between

1、描述:

當(dāng)前請求在指定時間中間才匹配

2、存在參數(shù):

????datetime1 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)
????datetime2 數(shù)據(jù)類型是 ZonedDateTime,帶有時區(qū)
???? 并且 datetime1 必須< datetime2

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Between=2020-11-01T11:08:08.020+08:00[Asia/Shanghai],2020-11-01T11:15:08.020+08:00[Asia/Shanghai]

4、Cookie

1、描述:

當(dāng)前請求中的cookie值匹配配置的cookie參數(shù)值時生效

2、存在參數(shù):

????name 請求cookie中的參數(shù)的名字
????regexp 請求cookie中的參數(shù)的值,配置的值是Java中的正則表達式形式。

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Cookie=token,tokenvalue\d+
Cookie.gif

4、解釋

  • Cookie=token,tokenvalue\d+
    表示 請求中必須存在一個 cookie 的key 是 token 的,且值必須是 tokenvalue 后面加上一個數(shù)子才匹配的上,否則匹配不上。

5、Header

1、描述:

當(dāng)前請求中的header值匹配配置的header參數(shù)值時生效

2、存在參數(shù):

????name header key的名字
????regexp header key對應(yīng)的值,配置的Java中的正則表達式形式。

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Header=X-Token-Id,\d+

4、解釋

  • Header=X-Token-Id,\d+
    表示請求頭中必須存在R-Token-Id且它的值必須是數(shù)字

6、Host

1、描述:

匹配請求頭中的Host的值

2、存在參數(shù):

????patterns 配置一系列的以.作為分隔的ant風(fēng)格host地址,多個中間以,隔開。Host中配置的值還支持URI template variables,比如{xxx}.baidu.com

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Host=**.gateway.com,{study}.baidu.com
Host匹配

4、解釋

  • Host=**.gateway.com,{study}.baidu.com
    1、**.gateway.com:表示請求中的Host的值需要配置這種ant風(fēng)格
    2、{study}.baidu.comstudy這個模版變量可以在GatewayFilter中獲取到,通過ServerWebExchange.getAttributes().get(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE)獲取

7、Method

1、描述:

匹配請求頭中的Method的值

2、存在參數(shù):

????methods 需要匹配的方法,比如GETPOST

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Method=GET,POST,PUT # 只有g(shù)et,post,put請求才能匹配上方這個路由

8、Path

1、描述:

匹配請求路徑。

2、存在參數(shù):

????patterns 需要匹配的路徑eg: /product/{id},/product/**
????matchOptionalTrailingSeparator 一個可選的參數(shù)

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - Path=/product/findOne/{productId},/product/**

4、解釋

/product/findOne/{productId} 支持uri模版變量,productId可以在GatewayFilter中獲取,獲取方式.

Map<string, string> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("productId");

9、Query

1、描述:

匹配請求參數(shù)。

2、存在參數(shù):

????param 請求參數(shù)的key值
????regexp 請求參數(shù)的值,配置的值是Java中的正則表達式形式。

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            #- Query=pwd
            - Query=username,\d+

4、解釋

1、Query=pwd 表示請求中必須存在 pwd這個請求參數(shù)
2、Query=username,\d+ 表示請求中必須存在username這個參數(shù),且它的值必須是數(shù)字

10、RemoteAddr

1、描述:

匹配請求的ip地址,支持ipv4和ipv6。

2、存在參數(shù):

????sources 地址列表eg:127.0.0.1/16 后方的/16是子網(wǎng)掩碼

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider # 名字唯一即可
          uri: lb://product-provider
          predicates:
            - RemoteAddr=127.0.0.1/16

4、注意

如果我們的Spring Cloud Gateway是位于代理后面,那么獲取到遠(yuǎn)程地址可能不正確,此時我們可以自己編寫一個RemoteAddressResolver來解決。

參考鏈接:https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#the-weight-route-predicate-factory

11、Weight

1、描述:

根據(jù)權(quán)重來分發(fā)請求,權(quán)重是根據(jù)group來計算的。

2、存在參數(shù):

????group 組,權(quán)重根據(jù)組來計算
????weight 權(quán)重值,是一個 Int 的值

3、配置實例

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider
          uri: https://weighthigh.org
          predicates:
            - Weight=group1,8
        - id: user-consumer
          uri: https://weightlow.org
          predicates:
            - Weight=group1,2

4、解釋

上方配置會導(dǎo)致80%的請求落到 https://weighthigh.org,有20%的請求落到https://weightlow.org

五、自己編寫一個 route predicate factory

1、編寫步驟

1、編寫一個類,實現(xiàn)RoutePredicateFactory接口,或繼承AbstractRoutePredicateFactory
????> 1、AbstractRoutePredicateFactory<c> 中的 C 表示 配置文件類
????> 2、重寫shortcutFieldOrder此方法,表示的配置文件中參數(shù)的位置
????> 3、重寫apply(C c)方法,表示的是具體的業(yè)務(wù)邏輯
2、我們自己編寫的類必須要以RoutePredicateFactory結(jié)尾,否則比較麻煩,參考
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#initFactories 這個方法。

2、要實現(xiàn)的功能

判斷請求參數(shù)中是否存在 token 配置的值。

3、Java代碼

@Slf4j
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<tokenroutepredicatefactory.config> {

    public TokenRoutePredicateFactory() {
        super(Config.class);
    }

    @Override
    public List<string> shortcutFieldOrder() {
        return Lists.newArrayList("token");
    }

    @Override
    public Predicate<serverwebexchange> apply(Config config) {
        return exchange -&gt; {
            log.info("判斷請求頭中是否存在token這個參數(shù)");
            String token = exchange.getRequest().getQueryParams().getFirst(config.getToken());
            return StringUtils.isNotBlank(token);
        };
    }

    @Data
    public static class Config {
        private String token;
    }
}

4、配置文件

spring:
  cloud:
    gateway:
      routes:
        - id: product-provider
          uri: lb://product-provider
          predicates:
            - Token=token

5、解釋

Java 編寫一個 Route Predicate Factory

六、完整代碼

https://gitee.com/huan1993/spring-cloud-alibaba-parent/tree/master/gateway

七、參考鏈接

https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容