⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://www.iocoder.cn/Fight/weishenmeweifuwuyidingyaoyouwangguan/ 「芋道源码」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

微服务拆得越细,有一个问题越无法回避:谁来管门?

系统从单体变成几十个服务后,每个服务都有自己的端口、认证逻辑、限流开关、日志格式。客户端查一个订单详情,可能要同时打会员、订单、商品三个接口——全部直接暴露在公网上。

这不是架构,这是散兵游勇。

微服务网关架构图:客户端通过 API 网关统一访问后端多个服务,网关承担路由、认证、限流、监控等职责

网关在所有服务前面立一道统一入口,把认证、路由、限流、日志这些和业务无关但又每个服务都要做的事情,统一收到一处处理。

没有网关会怎样

认证逻辑写 20 遍。20 个服务每个都要做 JWT 解析、验签、查黑名单。同一段代码写 20 遍,将来逻辑改了得 20 个服务全改全部署,漏改一处就是安全漏洞。抽到公共包?所有服务 jar 包变大,公共包有任何变动全得重新编译部署。

横切关注点到处散落。限流、日志、跨域——跟业务无关但每个服务都要处理。结果各团队各写各的:A 团队日志 JSON,B 团队纯文本;C 团队限流用 Guava,D 团队自己写滑动窗口。想做全局限流?找不到统一的地方改。

运维没有全局视角。灰度发布、AB 测试、全局拦截某类请求——没有网关就要改每个服务。

Nginx 能不能顶替? Nginx 性能强、稳定,但它做不了 JWT 解析、熔断降级,也跟不上注册中心。微服务的实例 IP 动态变化,Nginx 需要手动维护上游列表,而 Spring Cloud Gateway 直接从 Nacos 拉取服务列表、自动负载均衡。Nginx 负责最外层流量接入,微服务网关负责内部流量治理,两者分工而不是替代。

网关的本质:路由转发 + 过滤器链

网关 = 路由转发 + 过滤器链

路由转发:接收所有外部请求,按路径、请求头等规则转发到对应微服务。过滤器链:请求进出网关时经过一系列 Filter 加工——认证、限流、日志、熔断、跨域。

微服务网关模式图:客户端通过 API 网关单一入口访问多个微服务

网关自己注册到注册中心(Nacos/Eureka),能动态感知后端所有服务实例的变动。这是它和 Nginx 最大的不同:它是体系内的成员,不是掉在体系外的连接层。

统一认证:网关价值最高的能力

把 JWT 解析和校验收敛到网关层,下游服务一行相关代码都不用写。

// 从请求头取令牌
String token = request.getHeaders().getFirst("Authorization");

// 检查 Redis 黑名单
Mono<Boolean> logoutInRedis = reactiveStringRedisTemplate
.opsForValue().get(LOGOUT_REDIS_KEY_PREFIX + pureToken)
.map(s -> true).switchIfEmpty(Mono.just(false));

// 解析 JWT
Claims body = Jwts.parser().setSigningKey(secretBase64)
.parseClaimsJws(pureToken).getBody();

校验通过后注入用户信息给下游:

// 先清理外部传入的自定义头(防伪造)
httpHeaders.remove("X-Subject");
httpHeaders.remove("X-Channel");

// 注入网关解析到的用户信息
requestBuilder.header("X-Subject", subject);
requestBuilder.header("X-Channel", channel);

安全细节:网关必须先清除外部传入的 X-Subject 等头字段,再注入自己的解析结果,否则恶意请求可以伪造用户身份。

路由与负载均衡

Spring Cloud Gateway 的路由配置:

spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user-service/**
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order-service/**

lb:// 前缀从注册中心拉取实例做负载均衡。后端扩缩容、IP 变更,客户端完全无感。还能做 API 聚合——网关内部并行打多个服务再合并返回,移动端少发一次请求总比发两次好。

限流与熔断

Redis + Lua 令牌桶限流

不是给整个系统设一个 QPS 上限,而是 API 级别精准控制:下单接口限 500,查询接口限 2000。

-- Lua 脚本核心逻辑(Redis 原子执行,无竞态)
local filled_tokens = math.min(capacity, last_tokens + (delta * rate))
local allowed = filled_tokens >= requested

为什么用 Lua?Redis 执行 Lua 是原子性的,高并发下不会出现竞态条件。 限流配置存 Redis,支持动态调整,不需要重启网关。

URL 级别熔断

每个 URL 对应独立断路器,某个接口出问题只熔断这一个:

Setter setter = Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(getClass().getSimpleName()))
.andCommandKey(HystrixCommandKey.Factory.asKey(uriAsCommandKey));

目前主流方案是 Sentinel,提供可视化控制台,规则实时生效。

日志与链路追踪

网关是所有请求的必经之路,在这里收集访问日志天然覆盖所有接口:

// 请求日志 -> MQ 异步发送(不阻塞主线程)
accessLogService.logRequestBody(exchange, bodyStr);
accessLogService.logResponseBody(exchange, responseBody);

响应头注入 TraceId——线上出问题前端贴出 TraceId,后端在日志系统里追溯整个链路。一条 TraceId 贯穿所有服务。

主流网关横向对比

网关 优势 注意事项
Nginx 高性能、稳定 不具备业务逻辑处理能力
Spring Cloud Gateway Spring 全家桶集成 Java 技术栈首选
Kong 开源 API 网关鼻祖 路由超千条性能下降
Apache APISIX 云原生、多语言插件 文档仍在完善
Envoy CNCF 毕业,适合服务网格 C++ 开发,二次开发难

Java 栈首选 Spring Cloud Gateway,高性能多语言栈选 APISIX。

生产实践:C 端和 B 端为什么要拆两个网关

大流量系统往往将 C 端和 B 端网关拆分。以一个 6000 万用户系统为例:

能力 C 端网关 B 端网关
认证方式 JWT + SSO 登出 JWT + 游客模式 + RSA 签名
限流策略 API 精准限流 精准限流 + 智能限流
熔断降级 统一错误响应 URL 级别断路器 + fallback
路由管理 Apollo 配置中心 Redis 动态路由 + 本地快照

拆的原因:两端认证策略不同(B 端多了游客模式和 RSA 签名验证)、限流策略不同(B 端有智能联动限流)、路由管理方式不同(B 端变更频率更高需要更灵活)。担在一起会互相干扰。

常见问题

网关应该做什么? 认证、限流、路由、日志、跨域、熔断、请求改写、响应标准化。

网关不应该做什么? 业务逻辑。不要做数据聚合、不要调数据库、不要做复杂业务判断。网关是通道,不是业务处理节点。

什么时候拆多个网关? 不同客户端群体有明显不同的认证方式、流量特征、安全要求时。

网关会不会单点故障? 会。常见做法:网关前挂 Nginx/LVS,网关多实例部署,注册中心健康检测。网关尽量轻量化,做好压测估容量。

文章目录
  1. 1. 没有网关会怎样
  2. 2. 网关的本质:路由转发 + 过滤器链
  3. 3. 统一认证:网关价值最高的能力
  4. 4. 路由与负载均衡
  5. 5. 限流与熔断
    1. 5.0.1. Redis + Lua 令牌桶限流
    2. 5.0.2. URL 级别熔断
  • 6. 日志与链路追踪
  • 7. 主流网关横向对比
  • 8. 生产实践:C 端和 B 端为什么要拆两个网关
  • 9. 常见问题