Spring Cloud Gateway(MVC 版),一文详解!
🏆本文收录于《滚雪球学SpringBoot 3》:
https://blog.csdn.net/weixin_43970743/category_12795608.html,专门攻坚指数提升,本年度国内最系统+最专业+最详细(永久更新)。
本专栏致力打造最硬核 SpringBoot3 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。 如果想快速定位学习,可以看这篇【SpringBoot3教程导航帖】https://blog.csdn.net/weixin_43970743/article/details/151115907,你想学习的都被收集在内,快速投入学习!!两不误。
若还想学习更多,可直接前往《滚雪球学SpringBoot(全版本合集)》:https://blog.csdn.net/weixin_43970743/category_11599389.html,涵盖SpringBoot所有版本教学文章。
演示环境说明:
- 开发工具:IDEA 2021.3
- JDK版本: JDK 17(推荐使用 JDK 17 或更高版本,因为 Spring Boot 3.x 系列要求 Java 17,Spring Boot 3.5.4 基于 Spring Framework 6.x 和 Jakarta EE 9,它们都要求至少 JDK 17。)
- Spring Boot版本:3.5.4(于25年7月24日发布)
- Maven版本:3.8.2 (或更高)
- Gradle:(如果使用 Gradle 构建工具的话):推荐使用 Gradle 7.5 或更高版本,确保与 JDK 17 兼容。
- 操作系统:Windows 11
1) Reactive Gateway vs MVC Gateway(Tomcat / Virtual Threads)
编程模型差异
| 维度 | Reactive Gateway | MVC Gateway |
|---|---|---|
| Web 栈 | WebFlux(响应式) | Spring MVC(Servlet) |
| 路由 API | RouteLocator / Builder | WebMvc.fn 的 RouterFunctions.Builder |
| Filter 形态 | GlobalFilter / GatewayFilter | HandlerFilterFunction(before/after) |
| 线程模型 | 少量 EventLoop 线程 + 非阻塞 | 请求线程(可用平台线程或虚拟线程) |
MVC Gateway 的核心点是:它把网关能力“落”在 Spring WebMvc.fn 上(函数式路由、函数式过滤器),自定义扩展也围绕 RequestPredicate 与 HandlerFilterFunction 来做。
什么时候选 MVC Gateway
更适合这些场景:
- 你们体系本来就是 Servlet(Spring MVC + Tomcat),希望网关也保持一致(运维/排障/依赖生态更统一)。
- 下游调用是“阻塞式客户端”(如传统 HTTP client、JDBC 依赖较多、老项目多),用虚拟线程可以显著降低线程资源压力。
- 团队不想引入全套响应式心智模型(背压、调度器、reactive chain 调试等)。
2) 路由谓词(Predicates)与过滤器(Filters)
路由谓词:RequestPredicate
MVC Gateway 的路由匹配是 RequestPredicate(请求谓词)——匹配 path/header/cookie/method/query/time window 等。官方文档明确:它复用了很多 WebMvc.fn 的谓词实现,并提供网关专用谓词;谓词还能用 and() / or() 组合。
YAML 方式(MVC)长这样:
spring:
cloud:
gateway:
mvc:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
(上面这种结构在官方的 “Gateway Request Predicates” 里就是示例格式。)
过滤器:HandlerFilterFunction(before / after)
MVC Gateway 的过滤器是 HandlerFilterFunction,并且常用两类:
- before filter:转发前处理(鉴权、改 header、改 path、加 trace 等)
- after filter:拿到响应后处理(改响应头、脱敏、统一包装等)
官方在“自定义 Predicate 和 Filter”里写得很直白:你通常会实现 RequestPredicate 和 HandlerFilterFunction,并且过滤器天然分为 before/after 两种变体。
Java 路由 API(MVC 网关最推荐的写法之一)
MVC Gateway 的 Java Routes API 是基于 RouterFunctions.Builder,并提供 GatewayRouterFunctions.route(routeId) 来补齐网关需要的元数据(routeId 等)。
典型结构(概念示例):
@Bean
RouterFunction<ServerResponse> routes() {
return GatewayRouterFunctions.route("user_route")
.GET("/api/users/**", HandlerFunctions.http("http://user-service"))
.before(/* before filters */)
.after(/* after filters */)
.build();
}
(GatewayRouterFunctions.route(String) 的作用与原因在官方 Java Routes API 里有解释:它会加一个“前置过滤器”把 routeId 写入请求元数据。)
3) 集成 Token 校验与转发
这里拆成两件事:校验(Validation) 与 转发(Relay/Forward)。
A. Token 校验(网关做资源服务器)
常见做法:
- 网关作为 Resource Server:本地校验 JWT(公钥/JWK),或 introspection。
- 校验通过:把用户信息(sub、tenant、scope、roles)写入请求头/属性,转发给下游。
- 校验失败:直接在网关返回 401/403(减少下游压力)。
在 MVC Gateway 里,校验点通常放在 before filter:
- 读
Authorization: Bearer ... - 校验 JWT(Spring Security)
- 通过则
request.headers(...)增强、或写 attribute 给后续 filter 用 - 不通过则短路返回
实战建议:
- “校验”尽量在网关统一做(除非你们是强零信任、必须服务端再校验一遍)。
- 不要把用户原始 Token 透传到所有内部服务;可以改为透传最小必要 claims(或内部签发的短期 token)。
B. Token 转发(TokenRelay)
如果你们是 OAuth2 登录(网关拿到用户 token),并希望在转发给下游时自动携带 token,可以用 TokenRelay Filter。官方 Web MVC 文档里就列出了 TokenRelay Filter。
典型用途:
- 网关做 OAuth2 client(处理登录/回调/会话)
- 下游服务需要 Bearer token(或特定 header)
- 网关用 TokenRelay 自动把 token 放回请求再转发
4) 灰度发布(Canary Release)的路由规则实现
Canary 的核心就是:把“同一个业务入口”的流量按规则切到 Stable / Canary 两套下游。常见有 3 类规则:
规则 1:按比例(最常见)
- 90% → stable
- 10% → canary
在 Spring Cloud Gateway 生态里,大家经常用“权重/比例”思路做 demo(例如 GitHub 的 canary demo、以及文章示例)。
实现要点(工程化建议):
-
让“是否命中 canary”具备稳定性:同一个用户尽量一直命中同一个版本(避免体验抖动)
- 做法:对
userId / deviceId / cookie做 hash,再按阈值分桶(而不是纯随机)。
- 做法:对
-
让规则可动态调整:把比例做成配置中心参数(或数据库规则),“10% → 30% → 50% → 100%”。
规则 2:按人群(灰度白名单)
- Header:
X-Canary: true - Cookie:
canary=true - 或者命中某个用户/租户列表
这种非常适合:
- 内测团队、VIP 客户、灰度租户先用新版本
- 出问题一键撤回(删掉白名单即可)
而 MVC Gateway 的谓词体系正适合表达这类条件(Header/Cookie/Query/Path 等都是常用谓词类型)。
规则 3:按请求特征(按接口、按地域、按业务参数)
- 只有
/api/v2/**走 canary - 只有
region=eu走 canary - 只有特定商品类目/渠道走 canary
一套“可落地”的组合方案(推荐)
把 canary 拆成三层,方便演进:
- 先做人群灰度(白名单):最安全、最可控
- 再做按比例灰度:扩大覆盖面
- 最后全量切换:稳定后把 stable 下线
同时配套两条过滤器能力:
- before:鉴权 + 打标(把命中结果写入 header:
X-Release-Track=canary|stable) - after:观测与审计(把 track、routeId、下游实例写入日志/指标)
🧧福利赠与你🧧
无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G PDF编程电子书、简历模板、技术文章Markdown文档等海量资料。
ps:本文涉及所有源代码,均已上传至Gitee:
https://gitee.com/bugjun01/SpringBoot-demo开源,供同学们一对一参考 Gitee传送门https://gitee.com/bugjun01/SpringBoot-demo,同时,原创开源不易,欢迎给个star🌟,想体验下被🌟的感jio,非常感谢❗
🫵 Who am I?
我是 bug菌:
- 热活跃于 CSDN:
https://blog.csdn.net/weixin_43970743| 掘金:https://juejin.cn/user/695333581765240| InfoQ:https://www.infoq.cn/profile/4F581734D60B28/publish| 51CTO:https://blog.51cto.com/u_15700751| 华为云:https://bbs.huaweicloud.cn/community/usersnew/id_1582617489455371| 阿里云:https://developer.aliyun.com/profile/uolxikq5k3gke| 腾讯云:https://cloud.tencent.com/developer/user/10216480/articles等技术社区; - CSDN 博客之星 Top30、华为云多年度十佳博主&卓越贡献奖、掘金多年度人气作者 Top40;
- 掘金、InfoQ、51CTO 等平台签约及优质作者;
- 全网粉丝累计 30w+。
更多高质量技术内容及成长资料,可查看这个合集入口 👉 点击查看:https://bbs.csdn.net/topics/612438251 👈️
硬核技术公众号 「猿圈奇妙屋」https://bbs.csdn.net/topics/612438251 期待你的加入,一起进阶、一起打怪升级。
- End -
- 点赞
- 收藏
- 关注作者
评论(0)