美文网首页javaWeb学习
Spring Cloud Gateway Route Predi

Spring Cloud Gateway Route Predi

作者: huan1993 | 来源:发表于2020-11-01 14:42 被阅读0次

    一、需求

    记录Spring Cloud Gateway的一些用法,不对其原理进行过多的探究。

    二、基本组成

    1、简介

    Spring Cloud Gateway 是 基于Spring boot 5Spring Boot 2.0Project Reactor 等技术开发的网关。它旨在为微服务提供一个简单有效的方式来管理api路由。

    Spring Cloud Gateway 是基于 Netty 运行的,不能运行在传统的Servlet容器中作为War包运行。
    

    2、核型概念

    1、Route 路由

    Route是网关的基本组成单元,它是有一个ID,一个目标URI和一组predicates和一组filters组成,如果一组断言结果为真,则匹配路由,目标URI会被访问。
    注意:
    1、多个 Predicate 之间是 逻辑and 的关系。
    2、多个Predicate是从定义的顺序从上到下依次执行,也可以指定 order 属性的值。

    2、Predicate 谓语、断言

    Predicate 是Java 8 Function interface。输入类型是Spring Framework ServerWebExchange。可以用来匹配HTTP请求中的任何内容,例如headers 或者 parameters

    3、Filter 过滤器

    FilterGatewayFilter的实例。通过Filter我们可以在请求发送或返回下游服务时 修改 请求响应

    3、工作原理

    Spring Cloud Gateway的工作原理
    上图来自 Spring 官网。

    三、网关 Predicate配置方式

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

    快捷方式是由过滤器是的名称识别,后面紧跟=,在跟以逗号(,)分隔的参数值。

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

    上一个示例使用两个参数定义了Cookie Route Predicate Factory,这两个参数是cookie名称,mycookie和与mycookievalue匹配的值

    2、完全展开的参数(配置文件)

    name:指定谓词工厂的名字
    args:指定对应谓词工厂中的参数对应的值。

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

    这种方式配置和上面的快捷方式配置的是一个意思

    3、上方2种方式配置和代码对应关系

    上方2种方式配置和代码对应关系

    4、uri 值的方式

    1、以http开头

    当匹配到这个路由后,会跳转到这个地址。

    2、以 lb 开头

    eg:
         uri: lb://service-name
    解释:
    lb:表示负载均衡的意思
    service-name:值的是调用服务在注册中心注册的服务名。

    四、Route Predicate Factories

    Spring Cloud Gateway内置了特别多的路由谓词工厂,用来匹配http请求。当多个一起使用时,是and的关系,即需要所有的谓词工厂都匹配,才匹配这个路由。

    1、After

    1、描述:

    当前请求在指定时间之后才匹配

    2、存在参数:

        datetime 数据类型是 ZonedDateTime,带有时区

    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、描述:

    当前请求在指定时间之前才匹配

    2、存在参数:

        datetime 数据类型是 ZonedDateTime,带有时区

    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、描述:

    当前请求在指定时间中间才匹配

    2、存在参数:

        datetime1 数据类型是 ZonedDateTime,带有时区
        datetime2 数据类型是 ZonedDateTime,带有时区
         并且 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、描述:

    当前请求中的cookie值匹配配置的cookie参数值时生效

    2、存在参数:

        name 请求cookie中的参数的名字
        regexp 请求cookie中的参数的值,配置的值是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 后面加上一个数子才匹配的上,否则匹配不上。

    5、Header

    1、描述:

    当前请求中的header值匹配配置的header参数值时生效

    2、存在参数:

        name header key的名字
        regexp header key对应的值,配置的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且它的值必须是数字

    6、Host

    1、描述:

    匹配请求头中的Host的值

    2、存在参数:

        patterns 配置一系列的以.作为分隔的ant风格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风格
      2、{study}.baidu.comstudy这个模版变量可以在GatewayFilter中获取到,通过ServerWebExchange.getAttributes().get(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE)获取

    7、Method

    1、描述:

    匹配请求头中的Method的值

    2、存在参数:

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

    3、配置实例

    spring:
      cloud:
        gateway:
          routes:
            - id: product-provider # 名字唯一即可
              uri: lb://product-provider
              predicates:
                - Method=GET,POST,PUT # 只有get,post,put请求才能匹配上方这个路由
    

    8、Path

    1、描述:

    匹配请求路径。

    2、存在参数:

        patterns 需要匹配的路径eg: /product/{id},/product/**
        matchOptionalTrailingSeparator 一个可选的参数

    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、描述:

    匹配请求参数。

    2、存在参数:

        param 请求参数的key值
        regexp 请求参数的值,配置的值是Java中的正则表达式形式。

    3、配置实例

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

    4、解释

    1、Query=pwd 表示请求中必须存在 pwd这个请求参数
    2、Query=username,\d+ 表示请求中必须存在username这个参数,且它的值必须是数字

    10、RemoteAddr

    1、描述:

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

    2、存在参数:

        sources 地址列表eg:127.0.0.1/16 后方的/16是子网掩码

    3、配置实例

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

    4、注意

    如果我们的Spring Cloud Gateway是位于代理后面,那么获取到远程地址可能不正确,此时我们可以自己编写一个RemoteAddressResolver来解决。

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

    11、Weight

    1、描述:

    根据权重来分发请求,权重是根据group来计算的。

    2、存在参数:

        group 组,权重根据组来计算
        weight 权重值,是一个 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、解释

    上方配置会导致80%的请求落到 https://weighthigh.org,有20%的请求落到https://weightlow.org

    五、自己编写一个 route predicate factory

    1、编写步骤

    1、编写一个类,实现RoutePredicateFactory接口,或继承AbstractRoutePredicateFactory
        > 1、AbstractRoutePredicateFactory<c> 中的 C 表示 配置文件类
        > 2、重写shortcutFieldOrder此方法,表示的配置文件中参数的位置
        > 3、重写apply(C c)方法,表示的是具体的业务逻辑
    2、我们自己编写的类必须要以RoutePredicateFactory结尾,否则比较麻烦,参考
    org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#initFactories 这个方法。

    2、要实现的功能

    判断请求参数中是否存在 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这个参数");
                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/

    相关文章

      网友评论

        本文标题:Spring Cloud Gateway Route Predi

        本文链接:https://www.haomeiwen.com/subject/apoyvktx.html