目录
- 前言
- [一、Spring Cloud Gateway 是什么?](#一、Spring Cloud Gateway 是什么?)
- [二、为什么需要 Gateway?](#二、为什么需要 Gateway?)
- [三、Gateway 能做什么?](#三、Gateway 能做什么?)
-
- [1. 路由转发(最核心)](#1. 路由转发(最核心))
- [2. 统一鉴权(JWT)](#2. 统一鉴权(JWT))
- [3. 负载均衡](#3. 负载均衡)
- [4. 限流](#4. 限流)
- [5. 统一日志](#5. 统一日志)
- [6. 跨域处理(CORS)](#6. 跨域处理(CORS))
- [7. 熔断降级](#7. 熔断降级)
- [四、Gateway 和 Nginx 有什么区别?](#四、Gateway 和 Nginx 有什么区别?)
- [五、Gateway 底层是什么?](#五、Gateway 底层是什么?)
- [六、Gateway 核心概念](#六、Gateway 核心概念)
-
- [1. Route(路由)](#1. Route(路由))
- [2. Predicate(断言)](#2. Predicate(断言))
- [3. Filter(过滤器)](#3. Filter(过滤器))
- [七、如何引入 Gateway?](#七、如何引入 Gateway?)
- [八、最简单的 Gateway 示例](#八、最简单的 Gateway 示例)
-
- [1. 创建 Gateway 项目](#1. 创建 Gateway 项目)
- [2. 添加依赖](#2. 添加依赖)
- [3. application.yml](#3. application.yml)
- [4. 启动 user-service 微服务](#4. 启动 user-service 微服务)
- [5. 启动 pay_route 微服务](#5. 启动 pay_route 微服务)
- [6. 测试](#6. 测试)
- [九、StripPrefix 过滤器(非常常用)](#九、StripPrefix 过滤器(非常常用))
- [十、Gateway 过滤器(重点)](#十、Gateway 过滤器(重点))
- [十一、Gateway + Nacos/Eureka](#十一、Gateway + Nacos/Eureka)
-
- [1.如果直接写 IP 会怎样?](#1.如果直接写 IP 会怎样?)
- [2.写多个 IP 可以吗?](#2.写多个 IP 可以吗?)
- 3.微服务实例是动态变化的
- 4.服务名才是固定的
- [5.lb:// 到底是什么?](#5.lb:// 到底是什么?)
- 6.请求流程
- [7.LoadBalancer 是什么?](#7.LoadBalancer 是什么?)
- 8.最常见的负载均衡算法
-
- [(1) 轮询(默认)](#(1) 轮询(默认))
- [(2) 随机](#(2) 随机)
- [(3 ) 权重](#(3 ) 权重)
- 9.以前是谁做负载均衡?
- 10.总结
- [十二、Gateway 为什么越来越重要?](#十二、Gateway 为什么越来越重要?)
- [十三、Gateway 的优点](#十三、Gateway 的优点)
- [十四、Gateway 的缺点](#十四、Gateway 的缺点)
- 十五、企业真实架构
- 十六、需要掌握的重点
- 十七、学习路线建议
- 十八、官方学习资源
前言
它是 Spring Cloud 微服务体系中的:
API 网关(API Gateway)
也是现在 Spring Cloud 官方推荐的网关方案,用来替代以前的 Netflix Zuul。 (
一、Spring Cloud Gateway 是什么?
你可以把它理解成:
微服务系统的"统一入口"
客户端(前端、APP、浏览器)不再直接访问各个微服务,而是:
text
用户
↓
Gateway 网关
↓
订单服务
用户服务
支付服务
库存服务
所有请求先进入 Gateway。
Gateway 再决定:
- 请求转发给谁
- 是否需要登录
- 是否限流
- 是否记录日志
- 是否鉴权
- 是否修改请求
- 是否熔断
- 是否负载均衡
二、为什么需要 Gateway?
如果没有网关:
text
前端
├── user-service:8081
├── order-service:8082
├── pay-service:8083
└── stock-service:8084
问题很多:
- 前端需要记住所有服务地址
- 登录校验每个服务都要写
- 限流每个服务都要做
- 跨域处理麻烦
- 日志分散
- 服务地址变化影响前端
而 Gateway:
text
前端
↓
gateway:9000
↓
各种微服务
前端只需要访问一个地址:
text
http://gateway:9000
这就是:API 网关模式
三、Gateway 能做什么?
Spring Cloud Gateway 最核心的作用:
1. 路由转发(最核心)
例如:
text
/api/user/** → user-service
/api/order/** → order-service
用户请求:
text
GET /api/user/1
Gateway 自动转发:
text
http://user-service/1
2. 统一鉴权(JWT)
例如:
text
Authorization: Bearer xxx
Gateway:
- 验证 token
- 判断是否登录
- 判断权限
通过后才允许进入微服务。
这样:
- 所有服务不用重复写 JWT 校验
- 权限逻辑统一
这是企业里非常常见的做法。
3. 负载均衡
Gateway 可以结合:
- Spring Cloud
- Eureka
- Nacos
- Consul
自动找到服务实例。
例如:
text
user-service
├── 10.0.0.1
├── 10.0.0.2
└── 10.0.0.3
Gateway 自动轮询。
4. 限流
防止接口被刷爆:
text
1 秒最多 100 请求
例如:
- 秒杀
- 登录接口
- 验证码接口
非常重要。
5. 统一日志
Gateway 可以:
- 记录请求时间
- 记录 IP
- 记录请求参数
- 记录响应时间
因为所有请求都会经过它。
6. 跨域处理(CORS)
前后端分离里很常见。
很多公司:
- 不在业务服务处理跨域
- 而是在 Gateway 统一处理
Reddit 上很多人讨论过这个问题。 (Reddit)
7. 熔断降级
比如:
text
支付服务挂了
Gateway 可以:
- 返回默认结果
- 返回"系统繁忙"
- 防止整个系统雪崩
四、Gateway 和 Nginx 有什么区别?
很多新人容易混淆。
1.Nginx
更偏:
- 网络层
- HTTP服务器
- 反向代理
- 静态资源
性能极高。
2.Gateway
更偏:
- Java代码逻辑
- Spring生态
- 微服务治理
它能:
- 获取 Spring Bean
- 调用 Redis
- 校验 JWT
- 调用数据库
- 使用过滤器
很多公司:
text
Nginx
↓
Gateway
↓
微服务
一起使用。
五、Gateway 底层是什么?
Spring Cloud Gateway:
基于:
- Spring WebFlux
- Reactor
- Netty
构建。 (Spring Cloud)
所以它: 是响应式(Reactive)网关
不是传统 Servlet 模型。
六、Gateway 核心概念
Gateway 最重要三个概念:
1. Route(路由)
决定:
text
请求转发给谁
例如:
yaml
routes:
- id: user_route
uri: http://localhost:8081
2. Predicate(断言)
决定:
text
什么请求匹配这个路由
例如:
yaml
predicates:
- Path=/user/**
表示:
text
/user/** 才匹配
官方文档里有很多 Predicate: (Spring Cloud)
例如:
- Path
- Method
- Header
- Cookie
- Query
- Host
3. Filter(过滤器)
决定:
text
请求和响应怎么处理
例如:
- JWT校验
- 添加请求头
- 打日志
- 修改路径
- 限流
这是 Gateway 最强大的部分。
七、如何引入 Gateway?
Maven
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
官方也是这样引入。 (Spring Cloud)
八、最简单的 Gateway 示例
假设你有 user、pay 两个微服务,每个微服务有都是多集群的
java
user-service
├── 10.0.0.1
├── 10.0.0.2
└── 10.0.0.3
pay-service
├── 10.0.0.4
├── 10.0.0.5
└── 10.0.0.6
1. 创建 Gateway 项目
例如:
text
gateway-server
2. 添加依赖
xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
3. application.yml
yaml
server:
port: 9000
spring:
cloud:
gateway:
routes:
- id: user_route
uri: http://localhost:8081
predicates:
- Path=/user/**
- id: pay_route
uri: http://localhost:8082
predicates:
- Path=/api/pay/**
4. 启动 user-service 微服务
例如:
text
localhost:8081
接口:
java
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/hello")
public String hello() {
return "hello user";
}
}
5. 启动 pay_route 微服务
例如:
text
localhost:8082
接口:
java
@RestController
@RequestMapping("/pay")
public class UserController {
@GetMapping("/money")
public String hello() {
return "pay ok";
}
}
6. 测试
(1)访问:
text
http://localhost:9000/user/hello
实际会被 Gateway 转发到 user 微服务:
text
http://localhost:8081/user/hello
(2)访问:
text
http://localhost:9000/pay/money
实际会被 Gateway 转发到 pay 微服务:
text
http://localhost:8082/pay/money
以 访问 http://localhost:9000/user/hello 详细说明:
用户访问:
java
http://localhost:9000/user/hello
Gateway:
java
匹配:
Path=/api/user/**
找到
java
uri: http://localhost:8081
然后去 Nacos 查询:
java
user-service
10.0.0.1
10.0.0.2
10.0.0.3
假设采用轮询:
第一次:10.0.0.1 ,第二次:10.0.0.2,第三次:10.0.0.3, 第四次:10.0.0.1
九、StripPrefix 过滤器(非常常用)
企业里极常见,很多公司会统一 API 前缀,或者隐藏后端服务的真实接口路径
例如:
java
/api/user/**
/api/order/**
/api/pay/**
或者:
java
/api/v1/user/**
/api/v1/order/**
/api/v1/pay/**
这样前端接口风格统一.
但后端服务通常不会写:
java
@RequestMapping("/api/v1/user")
而是写:
java
@RequestMapping("/user")
因此需要 Gateway 在转发时把公共前缀删掉。
如何进行配置进行去除前端发送过来的多余的请求前缀呢?
例如:
yaml
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
用户请求:
text
/api/user/hello
Gateway 转发:
text
/user/hello
这段配置是 Spring Cloud Gateway 中最经典的路由转发规则,它的作用是"拦截特定路径的请求,并在转发给下游服务前,去掉第一层路径前缀",即去掉 /api。
我们可以把它拆解成两个部分来理解:
predicates: - Path=/api/user/**(断言/匹配规则)
这相当于网关的 "门卫",负责判断哪些请求需要被这条路由规则接管。
含义:它会拦截所有以 /api/user/ 开头的 HTTP 请求。
举例:像 /api/user/login、/api/user/info、/api/user/v1/profile 这样的请求都会被这个断言成功匹配并捕获。
filters: - StripPrefix=1(过滤器/处理动作)
这相当于对捕获到的请求进行"加工"。
含义:在把请求真正转发给后端微服务之前,剥离掉原始请求路径中的第 1 个层级。
作用:通常用于隐藏后端服务的真实接口路径,或者统一对外暴露的 API 规范。
再来一个示例,如果你想匹配 /api/v1/user/开头的接口,然后去掉前面 2 层,即去除 /api/v1 ,可以像下面这样写:
yaml
predicates:
- Path=/api/v1/user/**
filters:
- StripPrefix=2
十、Gateway 过滤器(重点)
1.局部过滤器
只对某个路由生效:
yaml
filters:
- AddRequestHeader=token,123
2.全局过滤器
对所有请求生效:
java
@Component
public class AuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(
ServerWebExchange exchange,
GatewayFilterChain chain) {
String token = exchange.getRequest()
.getHeaders()
.getFirst("token");
if(token == null){
exchange.getResponse()
.setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
这就是:
text
统一登录校验
十一、Gateway + Nacos/Eureka
再企业里通常不会在配置文件中:
yaml
uri: http://localhost:8081
企业里通常这样:
yaml
uri: lb://user-service
这里:
text
lb
表示: LoadBalance
Gateway 自动从 Nacos/Eureka 注册中心找到服务。
明明知道 user-service 的 IP,为什么不直接写 IP?
为什么写
lb://user-service?
实际上这正是微服务和传统单体应用的重要区别。
1.如果直接写 IP 会怎样?
yaml
spring:
cloud:
gateway:
routes:
- id: user
uri: http://10.0.0.1:8080
predicates:
- Path=/user/**
此时请求流程:
java
Gateway
↓
10.0.0.1:8080
看起来没问题。
但是如果有多个实例:
java
user-service
├── 10.0.0.1:8080
├── 10.0.0.2:8080
└── 10.0.0.3:8080
你写哪个?如果你配置文件里 uri: http://10.0.0.1:8080 这样配置,其它两台机器根本没用到。
2.写多个 IP 可以吗?
有人会想到:
java
uri:
- http://10.0.0.1:8080
- http://10.0.0.2:8080
- http://10.0.0.3:8080
问题又来了。
如果:
java
10.0.0.2 宕机
你必须修改配置:
java
删除 10.0.0.2
然后重启 Gateway,但是生产环境根本无法接受这样操作。
3.微服务实例是动态变化的
现实情况:
现实情况:
上午:
java
user-service
10.0.0.1
10.0.0.2
10.0.0.3
中午流量变大:
java
user-service
10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
10.0.0.5
晚上流量变小:
java
user-service
10.0.0.1
10.0.0.2
特别是 Kubernetes 环境:
java
Pod
创建
销毁
重建
迁移
IP 经常变化。
你根本不可能手工维护。
4.服务名才是固定的
虽然 IP 经常变:
java
10.0.0.1
10.0.0.2
10.0.0.3
但是服务名不变:
java
user-service
所以注册中心记录:
java
user-service
↓
10.0.0.1
user-service
↓
10.0.0.2
user-service
↓
10.0.0.3
Gateway 只关心:
java
lb://user-service
至于具体 IP:
java
注册中心负责维护
5.lb:// 到底是什么?
这里:
yaml
uri: lb://user-service
不是 URL。
而是:
text
LoadBalancer 协议
意思是:
text
请通过负载均衡器寻找 user-service
Gateway 看到:
yaml
lb://user-service
执行:
text
1 查询注册中心
2 获取实例列表
3 负载均衡
4 选择一个实例
5 转发请求
6.请求流程
假设:
text
user-service
10.0.0.1
10.0.0.2
10.0.0.3
用户访问:
text
GET /user/list
Gateway:
yaml
uri: lb://user-service
↓
去 Nacos 查询:
text
user-service
10.0.0.1
10.0.0.2
10.0.0.3
↓
Spring Cloud LoadBalancer 选择:
text
10.0.0.2
↓
转发:
text
http://10.0.0.2:8080/user/list
7.LoadBalancer 是什么?
Spring Cloud 里的:
text
Spring Cloud LoadBalancer
负责:
从多个实例中选择一个实例
例如:
text
user-service
10.0.0.1
10.0.0.2
10.0.0.3
LoadBalancer 决定:
text
本次请求发给谁
8.最常见的负载均衡算法
(1) 轮询(默认)
text
请求1 → 10.0.0.1
请求2 → 10.0.0.2
请求3 → 10.0.0.3
请求4 → 10.0.0.1
循环。
(2) 随机
text
请求1 → 10.0.0.3
请求2 → 10.0.0.1
请求3 → 10.0.0.2
随机选择。
(3 ) 权重
假设:
text
10.0.0.1 权重=5
10.0.0.2 权重=3
10.0.0.3 权重=2
那么:
text
50%
30%
20%
的流量进入。
9.以前是谁做负载均衡?
老版本 Spring Cloud:
使用的是:
Ribbon
text
Gateway
↓
Ribbon
↓
Nacos/Eureka
但是 Ribbon 已经停止维护。
现在:
text
Gateway
↓
Spring Cloud LoadBalancer
↓
Nacos/Eureka
官方推荐这个方案。
10.总结
Gateway 中为什么使用 lb://user-service,而不是直接写 IP?
因为微服务实例数量和 IP 是动态变化的,
服务名是固定的。
Gateway 通过 lb:// 服务名访问服务,
再由注册中心返回实例列表,
最后由 Spring Cloud LoadBalancer
按照负载均衡策略选择具体实例。
这样实现了服务发现和负载均衡,
避免了硬编码 IP。
所以在微服务体系里:
java
Nacos/Eureka/Zookeeper
↓
服务发现
Spring Cloud LoadBalancer
↓
负载均衡
Spring Cloud Gateway
↓
请求路由
十二、Gateway 为什么越来越重要?
现在微服务系统:
- 服务越来越多
- 安全越来越复杂
- 前后端分离越来越普遍
所以: API Gateway 几乎已经是标配
甚至 Kubernetes 环境里很多公司依然使用它。
十三、Gateway 的优点
| 优点 | 说明 |
|---|---|
| 统一入口 | 前端只访问一个地址 |
| 统一鉴权 | JWT统一校验 |
| 限流 | 防止接口被刷 |
| 负载均衡 | 自动分发请求 |
| 路由转发 | 动态转发服务 |
| 日志监控 | 统一处理 |
| 熔断降级 | 提高系统稳定性 |
| 与Spring整合 | 非常方便 |
十四、Gateway 的缺点
| 缺点 | 说明 |
|---|---|
| 学习成本高 | WebFlux 响应式 |
| 调试复杂 | 异步链路 |
| 不适合阻塞代码 | 不能随便 Thread.sleep |
| 容易成为单点 | 需要集群部署 |
十五、企业真实架构
很多公司:
text
前端
↓
Nginx
↓
Gateway
↓
认证服务
用户服务
订单服务
支付服务
Gateway 常常负责:
- JWT
- 限流
- 灰度发布
- 黑名单
- API版本
- 统一异常处理
十六、需要掌握的重点
必学
- Gateway 路由
- Predicate
- Filter
- GlobalFilter
- JWT鉴权
- Nacos/Eureka整合
- StripPrefix
- CORS
进阶
- 限流
- 熔断
- Sentinel
- Redis令牌桶
- 灰度发布
- 链路追踪
高级
- Reactor
- WebFlux
- Mono
- Flux
- Netty
十七、学习路线建议
建议顺序:
text
1. 先学 Gateway 路由
2. 学 Filter
3. 学 JWT 鉴权
4. 学 Nacos 整合
5. 学 限流
6. 学 Sentinel
7. 学 WebFlux
十八、官方学习资源
其他可拓展:
- Gateway 完整项目实战
- Gateway + JWT 登录鉴权
- Gateway + Nacos
- Gateway 全局过滤器源码解析
- Gateway 底层原理(WebFlux/Reactor)
- 企业级 Gateway 架构
- Gateway 限流实现
- Gateway 与 Nginx 的协作
- Gateway 面试题
- 从零手写一个微服务网关项目