【SpringCloud】GateWay概述、路由配置、Predicate使用、FIlter使用

🔰 学习视频 🔰

尚硅谷SpringCloud框架开发教程(SpringCloudAlibaba微服务分布式架构丨Spring Cloud)

集数:65—73


🔰 学习格言 🔰

不在能知,乃在能行。


🔰 学习笔记 🔰

【Java】学习笔记汇总


🔰 项目地址 🔰

https://gitee.com/zqcliudaliuda/cloud2021


一、概述

Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的ZuuI网关;但在2.x版本中,zuul的升级一直跳票 ,SpringCloud最后自己研发了一个网关替代Zuul,那就是SpringCloud Gateway,一句话: gateway是原zuul1.x版的替代。

在这里插入图片描述

1.1 应用

反向代理、鉴权、流量控制、熔断、日志监控…

1.2 特性

  • 基于Spring Framework 5, Project Reactor和Spring Boot 2.0进行构建;
  • 动态路由:能够匹配任何请求属性;
  • 可以对路由指定Predicate (断言)和Filter(过滤器)
  • 集成Hystrix的断路器功能;
  • 集成Spring Cloud服务发现功能;
  • 易于编写的Predicate(断言)和Filter(过滤器) ;
  • 请求限流功能;
  • 支持路径重写。

1.3 三大核心概念

  • Route:路由,路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由。

  • Predicate:断言,参考Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。

  • Filter:过滤,指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

1.4 工作流程

web请求,通过一些匹配条件, 定位到真正的服务节点。并在这个转发过程的前后,进行些精细化控制。predicate就是我们的匹配条件;而filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。
在这里插入图片描述
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。

Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前( “pre” )或之后( “post” )执行业务逻辑。Filter在"pre" 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在"post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

二、入门配置

2.1 新建Module工程

新建maven项目cloud-gateway-gateway9527

2.2 POM

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>com.zqc.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>true</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>

2.3 application.xml

server:
  port: 9527

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

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

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

后面将介绍另一种配置方式。

2.4 主启动类

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run(GateWayMain9527.class, args);
    }
}

2.5 测试

依次启动:7001、cloud-provider-payment8001、9527网关

在Eureka中可查看到:
在这里插入图片描述

添加网管前访问:http://localhost:8001/payment/get/1
添加网管后访问:http://localhost:9527/payment/get/1

{"code":200,"message":"查询成功, serverPort:8001","data":{"id":1,"serial":"xxxx"}}

在这里插入图片描述

三、路由配置

3.1 配置文件

application.yml

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

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

3.2 RouteLocator

在9527中添加新的配置类。

@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_1",
                r -> r.path("/guonei")
                        .uri("http://new.baidu.com/guonei")).build();
        return routes.build();
    }
}

启动9527并访问:http://localhost:9527/guonei

四、通过服务名实现动态

默认情况下Gatway会根据注册中心注册的服务列表, 以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。

4.1 application.yml

修改9527的application.yml

添加动态路由,并将uri: http://localhost:8001修改为uri: lb://cloud-payment-service

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true   # 开启从注册中心动态创建路由功能,利用微服务名进行路由
      routes:
        - id: payment_routh        # 路由的ID,没有固定规则但要求唯一,建议配合服务名
          # uri: http://localhost:8001  # 匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/**  # 断言,路径相匹配的进行路由

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

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

4.2 测试

依次启动:7001、cloud-provider-payment8001、8002、9527

访问:http://localhost:9527/payment/get/1

{"code":200,"message":"查询成功, serverPort:8002","data":{"id":1,"serial":"xxxx"}}
{"code":200,"message":"查询成功, serverPort:8001","data":{"id":1,"serial":"xxxx"}}

同样实现了负载均衡。

五、Predicate使用

在yml中配置的predicate是path
在这里插入图片描述
官方:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

详细说明都在官网的介绍里面。

5.1 After、Before、Between

表示在该时间后,路由才生效。(After、Before、Between同理)
在这里插入图片描述

如何获得时间戳:

ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
System.out.println(zbj);

// 2021-11-15T20:09:01.647+08:00[Asia/Shanghai]

5.2 Cookie

Cookie Route Predicate需要两个参数,一个是Cookie name,一个是正则表达式。

路由规则会通过获取对应的Cookie name值喝正则表达式去匹配,如果匹配上就回去执行路由,如果没匹配上不执行。

🔶 修改配置
在这里插入图片描述
🔶 测试

使用crul进行测试,打开命令行工具

命令:curl http://localhost:9527/payment/get/1

此时不带cookie访问,结果是404,查询失败。
在这里插入图片描述
命令:curl http://localhost:9527/payment/get/1 --cookie "username=zzyy"

此时带cookie访问,结果为200,查询成功。
在这里插入图片描述

5.3 Header

两个参数: 一个是属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。
在这里插入图片描述
访问:curl http://localhost:9527/payment/get/1 失败
访问:curl http://localhost:9527/payment/get/1 -H "X-Request-Id:123" 成功

六、Filter使用

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。Spring Cloud Gateway内置了多种路由过滤器,他们都由GatewayFilter的工厂 类来产生

Filter包含两种:GatewayFilterGlobalFilter

🔶 自定义过滤器

一般使用自定义过滤器,不用官网提供的。

cloud-gateway-gateway9527中添加类MyLogGateWayFilter,过滤用户。

@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("-----------------com in MyLogGateWayFilter: " + new Date());
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if (uname == null) {
            log.info("用户名为null,非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

在这里插入图片描述

注释掉路由断言的条件,重启9527,

访问:http://localhost:9527/payment/get/1?uname=z3 成功
访问:http://localhost:9527/payment/get/1 错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望天边星宿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值