Spring Cloud Gateway 路由
Spring Cloud Gateway 路由完全指南
Spring Cloud Gateway 是 Spring 生态中基于 Spring WebFlux 的 API 网关,专为微服务架构设计。路由是其核心功能,它决定了请求如何被转发到下游服务。本教程将从零开始,带你掌握路由配置、谓词断言、过滤器以及动态路由,内容面向初学者,追求高信息密度与实践性。
什么是 Spring Cloud Gateway?
Spring Cloud Gateway 建立在 Spring Boot 2.x 和 Project Reactor 之上,提供了一种简单、有效的方式对 API 进行路由管理。它具备以下核心能力:
- 路由:将外部请求映射到内部微服务地址
- 断言:匹配请求的特征(路径、头信息、参数等)
- 过滤:在请求转发前或响应返回前修改报文
与 Zuul 1.x 相比,Gateway 使用非阻塞 I/O,支持长连接(如 WebSocket),性能更高,功能更现代。
路由基础概念
路由(Route)、断言(Predicate)和过滤器(Filter)是 Gateway 的三大组件,理解它们是掌握路由的前提。
路由(Route)
路由是一个完整的转发规则,由 ID(唯一标识)、目标 URI、一组谓词和一组过滤器组成。当谓词条件全部满足时,请求将被路由到目标 URI。
断言(Predicate)
断言是 Java 8 的 Predicate 接口,输入参数是 Spring Framework 的 ServerWebExchange。Gateway 内置了多种断言工厂,可以让你通过配置灵活定义匹配条件,如路径、请求方法、时间窗口等。
过滤器(Filter)
过滤器用于在请求被转发前后修改报文或执行额外逻辑。Gateway 分为两类过滤器:
- GatewayFilter:应用于单个路由
- GlobalFilter:全局作用于所有路由
过滤器可通过实现 GatewayFilterFactory 来自定义。
快速入门:创建第一个路由
让我们从最简示例开始,将一个以 /api/hello 开头的请求转发到本地 http://localhost:8080 的服务。
添加依赖
在 Spring Boot 项目的 pom.xml 中添加 Spring Cloud Gateway 依赖(Spring Cloud 版本需匹配):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置 application.yml
在 application.yml 中定义路由规则:
spring:
cloud:
gateway:
routes:
- id: hello_route
uri: http://localhost:8080
predicates:
- Path=/api/hello/**
解释:
id:路由的唯一标识,建议具有业务含义uri:目标服务地址,支持http、lb(负载均衡)等协议predicates:断言列表,这里匹配所有以/api/hello开头的请求路径
编写主类
常规的 Spring Boot 启动类,无需额外注解即可使用 Gateway 功能:
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
启动并测试
启动 Gateway 应用(默认端口 8080),随后访问 http://localhost:8080/api/hello。如果后端 http://localhost:8080 有对应接口,请求将被成功转发。
路由谓词详解
Gateway 内置了十几个谓词工厂,可通过组合它们实现精准匹配。以下是最常用的几种。
After/Before/Between 路由
基于时间的谓词,控制路由在特定时间窗口内生效。
predicates:
- After=2025-01-01T00:00:00.000+08:00[Asia/Shanghai] # 在此时间之后生效
- Before=2025-12-31T23:59:59.000+08:00[Asia/Shanghai] # 在此时间之前生效
- Between=2025-06-01T00:00:00.000+08:00[Asia/Shanghai], 2025-06-30T23:59:59.000+08:00[Asia/Shanghai] # 时间段内生效
Cookie/Header/Host 路由
根据 Cookie、Header 或请求主机进行匹配:
predicates:
- Cookie=chocolate, ch.p # 含有 cookie chocolate 且值匹配正则 ch.p
- Header=X-Request-Id, \d+ # 头部 X-Request-Id 存在且为数字
- Host=**.example.com # Host 匹配 .example.com 的子域名
Method/Path/Query 路由
最常用的匹配方式:
Method:匹配 HTTP 方法,如 GET、POSTPath:匹配请求路径,支持 Ant 风格通配符Query:匹配查询参数,可指定参数名和可选的正则值
predicates:
- Method=GET,POST
- Path=/user/{segment} # 路径变量,可用于过滤器
- Query=version, v\d+ # 包含参数 version 且值匹配 v后面跟数字
权重路由
权重路由可以将流量按比例分发给不同目标,常用于灰度发布或 A/B 测试。它需要配合 Weight 路由谓词工厂,并在 group 下定义多个路由。
spring:
cloud:
gateway:
routes:
- id: version_v1
uri: http://localhost:8081
predicates:
- Path=/api/**
- Weight=group1, 80
- id: version_v2
uri: http://localhost:8082
predicates:
- Path=/api/**
- Weight=group1, 20
上方配置表示 /api/** 的请求中,80% 流向 v1 服务,20% 流向 v2 服务。同一 group 下所有权重要求和必须为 100。
路由过滤器
过滤器是 Gateway 扩展的核心,内置的过滤器工厂覆盖大多数场景,也支持自定义。
AddRequestHeader 过滤器
在转发请求时添加自定义请求头,适用于向下游传递额外信息。
filters:
- AddRequestHeader=X-Request-Foo, Bar
AddRequestParameter 过滤器
为下游服务添加请求参数:
filters:
- AddRequestParameter=flag, enabled
请求将被附加 ?flag=enabled。
RewritePath 过滤器
重写请求路径,常用于去除 API 前缀或重新组织路径结构。
filters:
- RewritePath=/api/(?<segment>.*), /$\{segment}
例如 /api/user/123 转发到下游时变为 /user/123。
自定义过滤器
实现自定义逻辑可继承 AbstractGatewayFilterFactory。下例创建一个记录请求耗时的过滤器:
@Component
public class ElapsedGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
long start = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
long elapsed = System.currentTimeMillis() - start;
System.out.println("Request took " + elapsed + "ms");
}));
};
}
}
在 yaml 中可直接使用 Elapsed 作为过滤器名(ElapsedGatewayFilterFactory 会去掉后缀)。
动态路由——结合注册中心
静态配置路由虽然简单,但微服务动态扩缩容场景下需要服务发现能力。Gateway 集成了多种注册中心,支持通过服务 ID 转发。
集成 Eureka
添加 Eureka 客户端依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置启用服务发现,并使用 lb 协议:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能
lowerCaseServiceId: true
routes:
- id: user_service_route
uri: lb://user-service # lb 表示负载均衡,user-service 为注册中心的服务名
predicates:
- Path=/user/**
此时 Gateway 会自动从 Eureka 订阅 user-service 的实例列表,实现负载均衡路由。
集成 Nacos
与 Eureka 类似,依赖替换为 spring-cloud-starter-alibaba-nacos-discovery,配置指向 Nacos 地址:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
enabled: true
routes:
- id: order_service_route
uri: lb://order-service
predicates:
- Path=/order/**
使用服务 ID 进行路由
开启 spring.cloud.gateway.discovery.locator.enabled=true 后,Gateway 会为每个注册中心的服务自动创建路由,规则为 /{serviceId}/**。例如服务 demo-service 会自动映射路径 /demo-service/**。你也可以继续自定义路由覆盖默认规则。
最佳实践与常见问题
- 路由顺序:多个路由可能匹配同一个请求,Gateway 按定义顺序依次匹配,第一个满足所有谓词的路由会被执行。注意将精确路由放在前面。
- 超时配置:通过
spring.cloud.gateway.httpclient.connect-timeout和response-timeout控制连接与响应超时,防止下游故障拖垮网关。 - 断路由:结合 Resilience4J 或 Sentinel 实现熔断,防止雪崩。
- 日志与监控:启用 Gateway 访问日志,结合 Actuator 端点查看路由列表、指标等。
- 避免简单转发:不应将 Gateway 作为透明代理,而应显式定义所有合法入口,关闭未声明的路径访问。
总结
Spring Cloud Gateway 的路由功能为我们提供了强大的 API 入口控制能力。通过声明式配置的谓词与过滤器,可以轻松实现请求匹配、转发、修改、限流与灰度发布。结合注册中心后,更能实现完全动态的服务寻址。掌握这些知识,你已能够在微服务体系中构建稳定、高效的网关层。
现在,你可以尝试添加更多路由谓词,编写自定义过滤器,并与 Eureka/Nacos 集成,让路由能力真正服务于你的业务。