Spring Cloud Gateway 基础使用(断言的使用)

1.Spring Cloud Gateway 是什么?

它是一个基于 Spring Framework 的开源 API 网关服务。它旨在为微服务架构中的应用程序提供统一的路由和过滤器机制,以实现请求的转发、降级、熔断、限流等功能。换言之,它就是网关(Gateway),充当了客户端和内部微服务之间的中介。

Spring Cloud Gateway 组成:

  1. 路由:定义请求应该被转发到哪个目标地址。
  2. 断言:用于匹配请求的条件,根据断言条件匹配到相应的路由。
  3. 过滤器:用于在请求路由前或路由后进行一些处理、操作,比如添加头部信息、修改请求体等。

在微服务中,内部之间的通讯是用 OpenFeign + LoadBalancer 实现的。那前端向后端发送请求的时候,我的访问路径是什么呢?该向哪一个服务发送呢?该用什么来统筹外部与内部之间的通信呢?其实就是使用 Spring Cloud Gateway 来提供统一访问地址或者定义一些规则来处理请求。

2. Gateway 的路由功能

2.1 准备工作

创建两个模块,来实现 Gateway 的路由功能。gateway-service 为网关,user-service 为一个服务。

gateway-servicepom. xml 中,添加依赖:

xml 复制代码
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

user-servicepom. xml 中,添加依赖:

xml 复制代码
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

注意,Spring Cloud Gateway 不能配合 Spring Web(Spring MVC) 一起使用。也就是在同一个 pom 文件中不能同时存在。

user-service 模块中随便写一个接口,然后配置 gateway 来实现路由的转发。

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getname")
    public String getName(){
        return "Name: 小明";
    }
}

2.2 配置路由

现在配置 gateway

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**

server:
  port: 8080

下面是 properties 格式的:

properties 复制代码
server.port=8080
spring.cloud.gateway.routes[0].id=userservice
spring.cloud.gateway.routes[0].uri=http://localhost:9090
spring.cloud.gateway.routes[0].predicates[0]=Path=/user/**
  • id: userservice,表示这个路由的唯一标识,不能重复,没有其他作用。
  • uri: http://localhost:9090,表示这个路由的目标地址。
  • predicates: 表示这个路由的断言列表,它有很多种类型,更多的类型后文介绍。
  • Path=/user/,表示这个断言的类型是 Path,用于匹配请求路径,这里表示匹配以/user/开头的任意路径。

这个路由规则的意思是,如果请求路径以/user/开头,就转发到http://localhost:9090这个地址。

user-service 配置:

yml 复制代码
server:
  port: 9090

启动程序后:

可以看到,localhost: 8080/user/getname 能访问到 9090 端口的 user-service 服务。这就实现了 localhost: 8080/user/getnamelocalhost: 9090/user/getname 路径的转换。

如果一个模块中有多个路由需要转换,就可以使用英文逗号隔开:

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**,/us/**,......
server:
  port: 8080

2.3 多个模块

再添加一个模块 goods-service

java 复制代码
@RestController
@RequestMapping("/goods")
public class GoodsController {

    @RequestMapping("/getname")
    public String getGoodsName(){
        return "红旗汽车";
    }
}
yml 复制代码
server:
  port: 7070

由于新增加一个模块,那么就需要添加一个路由设置。gateway 的配置文件:

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**
        - id: goodsservice
          uri: http://localhost:7070
          predicates:
            - Path=/goods/**
server:
  port: 8080

启动程序,并访问 localhost: 8080/goods/getname

可以看到 gateway 将不同的端口的服务整合到一起,这就是它的作用之一。

2.4 断言类型

Gateway 的断言类型有:

  • After、Before、Between:根据请求的时间进行路由,可以指定一个时间点或一个时间区间。
  • Cookie:根据请求中的cookie进行路由,可以指定cookie的名称和值的正则表达式。
  • Header:根据请求头进行路由,可以指定请求头的名称和值的正则表达式。
  • Host:根据请求的主机名进行路由,可以指定一个或多个主机名,也可以使用通配符。
  • Method:根据请求的方法进行路由,可以指定一个或多个HTTP方法,如GET、POST等。
  • Query:根据请求的查询参数进行路由,可以指定参数的名称和值的正则表达式。
  • Path:匹配请求路径。
  • Query:匹配请求参数。
  • RemoteAdder:匹配请求的 IP 地址。
  • Weight:根据权重来分发请求。
  • XForwardedRemoteAddr:根据 HTTP 头 X-Forwarded-For 进行请求过滤。

更详细的看官方文档: Spring Cloud Gateway

2.4.1 根据时间匹配

下面表示在 2024-01-28 T17:42:47.789 这个时间之后才会匹配路由,+08:00[Asia/Shanghai] 为时区。

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**
            - After=2024-01-28T17:42:47.789+08:00[Asia/Shanghai]

2017-01-20 T17:42:47.789~2017-01-21 T17:42:47.789 之间的请求可以被匹配。

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**
	        - Between=2017-01-20T17:42:47.789+08:00[Asia/Shanghai], 2017-01-21T17:42:47.789+08:00[Asia/Shanghai]

2.4.2 Header 断言

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**
        - id: goodsservice
          uri: http://localhost:7070
          predicates:
            - Path=/goods/**
            - Header=X-Request-Id, \d+

这个路由匹配条件是:如果请求包含名为 X-Request-Id 的头,并且该头的值与正则表达式 \d+ 匹配(即,它的值为一个或多个数字),则路由匹配。

(正则表达式的规则:正则表达式 -- 教程 | 菜鸟教程 (runoob.com)

没有 X-Request-Id 时 404:

添加 X-Request-Id 时,能访问:

2.4.3 Method 断言

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: http://localhost:9090
          predicates:
            - Path=/user/**
        - id: goodsservice
          uri: http://localhost:7070
          predicates:
            - Path=/goods/**
            - Method=GET,POST

只能匹配 GET、POST 类型的请求。

2.4.4 Weight 断言

yml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: userservice1
          uri: http://localhost:9090
          predicates:
            - Weight=group1,10
        - id: userservice2
          uri: http://localhost:7070
          predicates:
            - Weight=group1,90

假设 userservice1userservice2 模块都有"/user/getname"这个接口。上面的意思是:把大约 10% 的流量转发到 userservice1,而将大约 90% 的流量转发到 userservice2。要注意的是权重是按组计算 的,上面的两个模块同属于 group1,那么就将这一组按比例来分流。

(最后,Gateway 肯定需要结合 NacosLoadBalancer 来使用,这样才能发挥它的最大作用,本篇只介绍了 Gateway 的断言,其它(如过滤器)后续再更新......)

相关推荐
IT学长编程几秒前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇3 分钟前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码22 分钟前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
郭二哈1 小时前
C++——模板进阶、继承
java·服务器·c++
A尘埃1 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23071 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
沉登c1 小时前
幂等性接口实现
java·rpc
代码之光_19801 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端
科技资讯早知道2 小时前
java计算机毕设课设—坦克大战游戏
java·开发语言·游戏·毕业设计·课程设计·毕设
小比卡丘3 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言