文章目录
- Spring Cloud Gateway 统一服务入口
- 一、依赖版本
- Boot 4 与 Boot 3 差异
- 二、为什么需要网关
- 三、依赖与启动类
- 3.1 gateway/pom.xml
- 3.2 启动类
- 四、配置文件
- 4.1 application-dev.yml
- 4.3 路由字段说明
- 五、断言(Route Predicate)
- 六、过滤器(Gateway Filter)
- 七、总结
Spring Cloud Gateway 统一服务入口
一、依赖版本
| 组件 | 版本 | 说明 |
|---|---|---|
| Java | 21 | |
| Spring Boot | 4.1.0 | 父 POM 统一管理 |
| Spring Cloud | 2025.1.2 | spring-cloud-dependencies |
| Spring Cloud Alibaba | 2025.1.0.0 | spring-cloud-alibaba-dependencies |
父 POM 版本锁定:
<properties><java.version>21</java.version><spring-cloud.version>2025.1.2</spring-cloud.version><spring-cloud-alibaba.version>2025.1.0.0</spring-cloud-alibaba.version></properties>Boot 4 与 Boot 3 差异
| 对比项 | Boot 3 | Boot 4(当前项目) |
|---|---|---|
| Gateway 依赖 | spring-cloud-starter-gateway | spring-cloud-starter-gateway-server-webflux |
| 路由配置 | spring.cloud.gateway.routes | spring.cloud.gateway.server.webflux.routes |
| 默认过滤器 | spring.cloud.gateway.default-filters | spring.cloud.gateway.server.webflux.default-filters |
旧 starter 在 Cloud 2025 BOM 中已移除,继续使用会报依赖无法加载。
二、为什么需要网关
微服务拆分后,Nacos 解决注册发现,LoadBalancer 解决负载均衡,OpenFeign 解决服务间调用。但接口仍分散在各服务端口上:
| 问题 | 说明 |
|---|---|
| 入口分散 | 客户端需分别访问 8080、8081 等 |
| 重复鉴权 | 每个服务都要做权限校验 |
Gateway 作为统一入口:外部只访问9000,内部按路由转发到lb://order-service/lb://product-service。
| 服务 | 端口 | 注册名 |
|---|---|---|
| gateway | 9000 | gateway |
| order-service | 8080 | order-service |
| product-service | 8081 / 8082 / 8083 | product-service |
网关是否和拦截器切面等重复冗余?
网关过滤器(大门外):运行在请求进入微服务集群之前,是流量的大门。它属于WebFlux(Netty)层,不依赖 Servlet 容器。
拦截器/切面(大门内):运行在请求已经进入具体的微服务应用之后。它属于 Spring MVC(Servlet) 容器,依赖具体的 Controller 或 Service。
如果网关已经拦截(如 Token 过期),请求直接返回 401,根本不会到达拦截器和切面——这节省了内部服务的线程资源。
结论:网关管“能不能进门”,拦截器管“进门后坐哪”,切面管“坐下后具体怎么做”。三者配合,而不是互相替代。
三、依赖与启动类
3.1 gateway/pom.xml
<!-- Gateway WebFlux(Boot 4 新 starter,禁止引入 spring-boot-starter-web) --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway-server-webflux</artifactId></dependency><!-- lb://服务名 负载均衡(必须单独引入) --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><!-- Nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>3.2 启动类
@SpringBootApplication// Spring Boot 自动配置@EnableDiscoveryClient// 注册到 Nacos,服务名 gatewaypublicclassGatewayApplication{publicstaticvoidmain(String[]args){// 应用入口SpringApplication.run(GatewayApplication.class,args);}}四、配置文件
4.1 application-dev.yml
server:port:9000# 网关监听端口spring:cloud:nacos:discovery:server-addr:127.0.0.1:8848# Nacos 注册中心地址loadbalancer:nacos:enabled:true# 启用 Nacos 权重/集群负载均衡策略gateway:server:webflux:default-filters:-AddResponseHeader=X-Gateway,spring-cloud-gateway# 全局响应头routes:-id:order-route# 路由 IDuri:lb://order-service# 负载均衡转发到 order-servicepredicates:-Path=/order/**# 路径断言-Method=GET,POST# 方法断言filters:-AddRequestHeader=X-Request-Source,gateway# 添加请求头-id:product-route# 路由 IDuri:lb://product-service# 负载均衡转发到 product-servicepredicates:-Path=/product/**# 路径断言-Method=GET,POST# 方法断言filters:-AddRequestHeader=X-Request-Source,gateway# 添加请求头-id:product-by-id-route# 带 Query 断言的路由uri:lb://product-service# 目标服务predicates:-Path=/product/getProductById# 精确路径-Query=id,\d+# id 必须为数字-Method=GET# 仅 GETfilters:-AddRequestHeader=X-Matched-Route,product-by-id# 标记命中的路由-id:order-api-route# StripPrefix 示例路由uri:lb://order-service# 目标服务predicates:-Path=/api/order/**# /api/order/xxxfilters:-StripPrefix=1# 去掉 /api 前缀,转发为 /order/xxx-id:product-legacy-route# RewritePath 示例路由uri:lb://product-service# 目标服务predicates:-Path=/legacy/product/**# 旧路径filters:-RewritePath=/legacy/product/(?<segment>.*),/product/${segment}# 重写为新路径logging:level:org.springframework.cloud.gateway:debug# Gateway 调试日志org.springframework.cloud.loadbalancer:debug# 负载均衡调试日志4.3 路由字段说明
| 字段 | 说明 |
|---|---|
id | 路由唯一标识 |
uri | 目标地址;lb://服务名从 Nacos 取实例并负载均衡 |
predicates | 断言,全部满足才匹配(AND) |
filters | 匹配后对请求/响应的处理 |
五、断言(Route Predicate)
yml 中的断言字符串由Route Predicate Factory解析,多个断言默认AND关系。
| 名称 | 说明 | 配置示例 |
|---|---|---|
| Path | 路径匹配 | Path=/product/** |
| Method | HTTP 方法匹配 | Method=GET,POST |
| Query | Query 参数正则匹配 | Query=id, \d+ |
| After | 指定时间之后的请求 | After=2024-01-01T00:00:00.000+08:00[Asia/Shanghai] |
| Before | 指定时间之前的请求 | Before=2025-12-31T23:59:59.000+08:00[Asia/Shanghai] |
| Between | 两个时间之间的请求 | Between=开始时间, 结束时间 |
| Header | Header 值正则匹配 | Header=X-Request-Id, \d+ |
| Cookie | Cookie 值正则匹配 | Cookie=token, .+ |
| Host | 请求 Host 匹配 | Host=**.example.com |
| RemoteAddr | 请求 IP 段匹配 | RemoteAddr=192.168.1.1/24 |
时间断言设为未来时间时,当前请求会 404(路由不匹配)。
六、过滤器(Gateway Filter)
Predicate 决定走哪条路由,Filter 决定路上做什么。Filter 分Pre(转发后端前)和Post(响应返回前)。
| 名称 | 类型 | 说明 | 配置示例 |
|---|---|---|---|
| AddResponseHeader | GatewayFilter / default-filters | 添加响应 Header | AddResponseHeader=X-Gateway, spring-cloud-gateway |
| AddRequestHeader | GatewayFilter | 添加请求 Header | AddRequestHeader=X-Request-Source, gateway |
| AddRequestParameter | GatewayFilter | 添加 Query 参数 | AddRequestParameter=userName, bite |
| RemoveRequestHeader | GatewayFilter | 删除请求 Header | RemoveRequestHeader=X-Request-Foo |
| RemoveResponseHeader | GatewayFilter | 删除响应 Header | RemoveResponseHeader=X-Response-Foo |
| StripPrefix | GatewayFilter | 去掉路径前缀段 | StripPrefix=1 |
| RewritePath | GatewayFilter | 正则重写路径 | RewritePath=/legacy/product/(?<segment>.*), /product/${segment} |
| PrefixPath | GatewayFilter | 添加路径前缀 | PrefixPath=/api |
| RequestRateLimiter | GatewayFilter | 限流(需 Redis) | name: RequestRateLimiter+ redis 参数 |
| Retry | GatewayFilter | 失败重试 | name: Retry+retries: 3 |
| RequestSize | GatewayFilter | 限制请求体大小 | name: RequestSize+maxSize: 5000000 |
| LoadBalancerClientFilter | GlobalFilter | 解析lb://并负载均衡 | 内置,无需 yml |
| Gateway Metrics Filter | GlobalFilter | 监控指标 | 需 actuator |
执行顺序:order 越小越先执行;order 相同时defaultFilter>GatewayFilter>GlobalFilter。
七、总结
| 主题 | 要点 |
|---|---|
| 版本 | Boot 4.1.0 + Cloud 2025.1.2 + Alibaba 2025.1.0.0 + Java 21 |
| 依赖 | gateway-server-webflux+loadbalancer+nacos-discovery |
| 配置前缀 | spring.cloud.gateway.server.webflux.* |
| 入口 | gateway:9000 →lb://order-service/lb://product-service |
| 负载均衡 | loadbalancer.nacos.enabled: true |
| 断言 | 多条件 AND;Path / Method / Query 等 |
| 过滤器 | default-filters 全局;StripPrefix / RewritePath 路径变换 |