利用Spring Cloud Gateway Predicate优化微服务路由策略
一、Predicate简介
Spring Cloud Gateway 是 Spring 生态系统中用于构建 API 网关的框架,它基于 Project Reactor 和 Netty 构建,旨在提供一种高效且灵活的方式来处理 HTTP 请求和响应。
Spring Cloud Gateway 的路由配置中,predicates
(断言)用于定义哪些请求应该匹配特定的路由规则。
断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服务上。
根据源码可以看到Spring cloud gateway 的内置断言,可以看到核心10个内置Predicate
在 Spring Cloud Gateway 的配置中,Predicate
通常通过 predicates
字段定义,配合路由配置一起使用。它可以基于以下方面来进行请求匹配:
- 路径匹配(Path)
- 请求方法匹配(Method)
- 请求头匹配(Header)
- 请求参数匹配(Query Param)
- IP 地址匹配(IP)
- 主机名匹配(Host)
- 负载均衡支持(lb://)
Spring Cloud Gateway除了提供一系列内置的断言工厂,同时也支持自定义断言。
二、常见 Predicate 类型
2.1 Path Predicate
Path Predicate 用于根据请求的路径进行匹配。
predicates:- Path=/api/** # 匹配以 /api/ 开头的请求路径
-
示例:
Path=/api/**
匹配请求路径以/api/
开头的所有请求,包括/api/v1/users
、/api/v2/orders
等。 -
通配符:
**
表示匹配任意路径段。*
表示匹配单个路径段。
示例:
spring:application:name: spring-cloud-gateway-samplecloud:gateway:routes:- id: bloguri: http://blog.abc.compredicates:# 匹配路径转发- Path=/api-boot-datasource-switch.html
# 端口号
server:port: 9090
在上面的配置中,当访问http://localhost:9090/api-boot-datasource-switch.html
时就会被自动转发到http://blog.abc.com/api-boot-datasource-switch.html
,这里要注意完全匹配Path
的值时才会进行路由转发
2.2 Method Predicate
Method Predicate 用于根据请求的方法类型(GET、POST、PUT 等)进行匹配。
predicates:- Method=GET # 仅匹配 GET 请求
- 示例:
Method=POST
只会匹配 HTTP POST 方法的请求。
2.3 Header Predicate
Header Predicate 用于根据请求中的某些头信息进行匹配。
predicates:- Header=Content-Type=application/json # 匹配 Content-Type 头为 application/json 的请求
- 示例:
Header=X-Custom-Header=foo
匹配请求头中X-Custom-Header
值为foo
的请求。
2.4 Query Param Predicate
Query Param Predicate 用于根据请求 URL 中的查询参数进行匹配。
predicates:- Query=type=admin # 匹配 URL 中包含 ?type=admin 的请求
- 示例:
Query=user=admin
匹配 URL 中查询参数user=admin
的请求,如https://example.com?user=admin
。
2.5 Host Predicate
Host Predicate 用于根据请求的 Host
头进行匹配。
predicates:- Host=example.com # 匹配 Host 头为 example.com 的请求
- 示例:
Host=*.example.com
匹配example.com
域名下的所有子域名,如api.example.com
、blog.example.com
等。
2.6 IP Predicate
IP Predicate 用于根据请求源 IP 地址进行匹配。
predicates:- Ip=192.168.1.0/24 # 匹配来自 192.168.1.0/24 网段的请求
- 示例:
Ip=10.0.0.0/8
匹配来自10.0.0.0/8
网段的请求。
2.7 Accept Predicate
Accept Predicate 用于根据请求的 Accept
头部进行匹配。
predicates:- Accept=application/json # 匹配 Accept 头为 application/json 的请求
- 示例:
Accept=text/html
匹配Accept
头为text/html
的请求。
2.8 Composite Predicate
你可以将多个 Predicate 组合成一个复合条件,使用 and
、or
等逻辑操作符。
predicates:- Path=/api/** and Method=POST # 请求路径以 /api/ 开头,且请求方法为 POST- Path=/api/** or Query=user=admin # 请求路径以 /api/ 开头,或查询参数 user=admin
2.9 Cookie
-
用途:匹配请求中的 Cookie。
-
示例:
predicates:- Cookie=chocolate, choco\.value
匹配名为
chocolate
且值符合正则表达式choco\.value
的 Cookie。
2.10 After 和 Before
-
用途:基于时间戳匹配请求。
-
示例:
predicates:- After=2024-01-01T00:00:00+08:00[Asia/Shanghai]
匹配在指定日期之后发出的请求。
predicates:- Before=2024-01-01T00:00:00+08:00[Asia/Shanghai]
匹配在指定日期之前发出的请求。
2.11 Between
-
用途:结合
After
和Before
,匹配某一时间段内的请求。 -
示例:
predicates:- Between=2024-01-01T00:00:00+08:00[Asia/Shanghai],2024-01-31T23:59:59+08:00[Asia/Shanghai]
2.12 RemoteAddr
-
用途:匹配客户端 IP 地址或 CIDR 块。
-
示例:
predicates:- RemoteAddr=192.168.1.1/24
匹配来自特定网段的请求。
三、Predicate 的组合
Spring Cloud Gateway 允许你通过逻辑运算符(and
、or
)组合多个 Predicate,定义更复杂的路由匹配规则。你可以组合不同的 Predicate 来匹配路径、方法、头部、参数等。
示例 1:匹配路径为 /api/**
且请求方法为 POST 的请求:
predicates:- Path=/api/** and Method=POST
示例 2:匹配路径为 /api/**
或者查询参数 user=admin
的请求:
predicates:- Path=/api/** or Query=user=admin
示例 3:使用多个 and
来组合复杂的匹配条件:
predicates:- Path=/api/** and Method=GET and Header=Authorization=Bearer
这表示只有当请求路径为 /api/**
且请求方法为 GET
,且请求头中包含 Authorization: Bearer
时,才会匹配此路由。
常用组合示例
1) 匹配 GET 请求并带有 Authorization
头
predicates:- Method=GET and Header=Authorization=Bearer
2) 匹配特定域名和查询参数
predicates:- Host=api.example.com and Query=type=admin
3) 匹配路径和方法的组合
predicates:- Path=/products/** and Method=GET
4) 路径匹配和 IP 匹配
predicates:- Path=/api/** and Ip=192.168.1.0/24
四、自定义断言
除了使用内置的断言工厂外,还可以通过实现自己的 GatewayFilterFactory
来创建自定义断言。这使得你可以根据业务逻辑添加更加复杂的匹配条件。
示例:自定义断言
假设我们想要创建一个名为 Custom
的自定义断言,它可以根据请求体中的 JSON 字段进行匹配。
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import reactor.core.publisher.Mono;public class CustomPredicateFactory extends AbstractRoutePredicateFactory<CustomPredicateFactory.Config> {public CustomPredicateFactory() {super(Config.class);}@Overridepublic Mono<Boolean> applyAsync(Config config, ServerHttpRequest request) {// 实现具体的匹配逻辑return Mono.just(request.getHeaders().containsKey("Custom-Header"));}public static class Config {private String key;// Getters and setters}
}
然后在配置文件中引用这个自定义断言:
predicates:- name: Customargs:key: value
总结
-
Predicate
是 Spring Cloud Gateway 中定义路由匹配条件的核心组件,通过多个Predicate
条件,你可以灵活地匹配请求。 - 支持多种常见的匹配方式,包括路径、方法、头部、查询参数、IP、主机等。
- 可以组合多个
Predicate
以构建复杂的路由规则。 - 支持逻辑组合(如
and
、or
)来满足不同的路由需求。
通过灵活使用 Predicate
,你可以对不同的请求进行精准路由控制,从而实现高效的请求管理和流量分发。