微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

springcloud-一篇搞定GateWay

SpringCloud GateWay简介

SpringCloud Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

Spring Cloud Gateway的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

SpringCloud GateWay基本组件

  1. Route(路由)
  2. Predicate(断言)
  3. Filter(过滤器)

Route(路由)

路由是构建网关的基本模块,它由路由ID,需转发到目标微服务URI,以及一系列的Predicate(断言)和Filter(过滤)组成,如果请求符合Predicate,则匹配该路由,按该路由来处理请求

Predicate(断言)

断言说简单点,就是请求匹配条件。断言是定义匹配条件,如果请求符合条件,则该请求匹配断言所属的路由

Filter(过滤器)

在SpringCloud GateWay这里的Filter的使用场景是:当请求匹配了某个路由后,需要转发到某个微服务之前或之后做一些事情

image

SpringCloud GateWay基本使用

SpringCloud GateWay是以微服务模块作为载体的(也会注册注册中心上),需要创建一个maven项目作为微服务启动。关于pom.yml、主启动省略,主要说下application.yml的配置,如下:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由

上面gateway的配置大致说明下:有两个路由,分别是payment_routh和payment_routh2;以payment_routh为例,如果请求是匹配predicates的path,则由该路由进行处理并转发到http://localhost:8001

总结

上面的是基本的gateway配置,不过还存在问题:实际项目中某个微服务是作为集群来部署的,因此不能只写死一台服务器的地址,需要负载均衡转发到相同服务但不同实例上。下面则是动态路由的实现方式,能够解决此问题

SpringCloud GateWay之动态路由

动态路由只是uri发生了变化,如下:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-payment-service          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-payment-service          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**     # 断言,路径相匹配的进行路由

uri配置为: lb://服务名

SpringCloud GateWay之Predicate(断言)详细配置

上面示例的Predicate,只演示了path,这只是匹配条件之一,还有其他匹配条件,如下:

image


下面就一些例子,如下:

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-payment-service          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由
            - After=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]
            - Before=2020-02-05T15:10:03.685+08:00[Asia/Shanghai]
            - Cookie=username,zzyy
            - Host=**.atguigu.com
            - Query=username, \d+  # 要有参数名username并且值还要是整数才能路由
            - Method=GET

上面的例子表示请求必须:请求的时间在before时间之前,after时间之后,携带key为username,value为zzyy的Cookie,客户端域名需要匹配**.atguigu.com,请求参数中得有username,且值为正整数,请求方式为get。满足上述的条件,此断言才为true,才匹配此路由

SpringCloud GateWay之Filter(过滤器))详细使用

在SpringCloud GateWay的Filter分为:GatewayFilter 和 GlobalFilter;

  1. GatewayFilter只针对指定的路由生效。
  2. GlobalFilter对全部路由生效。

GatewayFilter示例

server:
  port: 9588

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能
          lower-case-service-id: true #使用小写服务名,认是大写
      routes:
        - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: lb://cloud-provider-payment #匹配后的目标服务地址,供服务的路由地址
          #uri: http://localhost:8001 #匹配后提供服务的路由地址
          filters:
            - AddRequestParameter=X-Request-Id,1024 #过滤器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id值为1024
          predicates:
            - Path=/paymentInfo/**        # 断言,路径相匹配的进行路由
            - Method=GET,POST

当请求匹配了payment_routh路由,就会执行AddRequestParameter这个过滤器进行过滤

GlobalFilter示例

@Component //必须加,必须加,必须加
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered
{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        log.info("time:"+new Date()+"\t 执行了自定义的全局过滤器: "+"MyLogGateWayFilter"+"hello");

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname == null) {
            System.out.println("****用户名为null,无法登录");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    //指定过滤器在过滤器的执行顺序,数值越小执行顺序越优先
    public int getorder()
    {
        return 0;
    }
}

不管请求匹配了哪个路由,都会执行gateway全局的过滤器。

总结

实际开发,GlobalFilter用的比较多,常用的使用场景是:全局日志,跨域处理,统一鉴权...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐