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 的断言,其它(如过滤器)后续再更新......)

相关推荐
Abladol-aj24 分钟前
并发和并行的基础知识
java·linux·windows
清水白石00824 分钟前
从一个“支付状态不一致“的bug,看大型分布式系统的“隐藏杀机“
java·数据库·bug
吾日三省吾码6 小时前
JVM 性能调优
java
弗拉唐7 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi777 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3438 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀8 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20208 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea
Ysjt | 深8 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++