前言

Spring Cloud Gateway 官方文档

它是 Spring Cloud 微服务体系中的:

API 网关(API Gateway)

也是现在 Spring Cloud 官方推荐的网关方案,用来替代以前的 Netflix Zuul。 (


一、Spring Cloud Gateway 是什么?

你可以把它理解成:

微服务系统的“统一入口”

客户端(前端、APP、浏览器)不再直接访问各个微服务,而是:

用户
  ↓
Gateway 网关
  ↓
订单服务
用户服务
支付服务
库存服务

所有请求先进入 Gateway。

Gateway 再决定:

  • 请求转发给谁
  • 是否需要登录
  • 是否限流
  • 是否记录日志
  • 是否鉴权
  • 是否修改请求
  • 是否熔断
  • 是否负载均衡

二、为什么需要 Gateway?

如果没有网关:

前端
 ├── user-service:8081
 ├── order-service:8082
 ├── pay-service:8083
 └── stock-service:8084

问题很多:

  • 前端需要记住所有服务地址
  • 登录校验每个服务都要写
  • 限流每个服务都要做
  • 跨域处理麻烦
  • 日志分散
  • 服务地址变化影响前端

而 Gateway:

前端
   ↓
gateway:9000
   ↓
各种微服务

前端只需要访问一个地址:

http://gateway:9000

这就是:API 网关模式


三、Gateway 能做什么?

Spring Cloud Gateway 最核心的作用:


1. 路由转发(最核心)

例如:

/api/user/**   → user-service
/api/order/**  → order-service

用户请求:

GET /api/user/1

Gateway 自动转发:

http://user-service/1

2. 统一鉴权(JWT)

例如:

Authorization: Bearer xxx

Gateway:

  • 验证 token
  • 判断是否登录
  • 判断权限

通过后才允许进入微服务。

这样:

  • 所有服务不用重复写 JWT 校验
  • 权限逻辑统一

这是企业里非常常见的做法。


3. 负载均衡

Gateway 可以结合:

自动找到服务实例。

例如:

user-service
 ├── 10.0.0.1
 ├── 10.0.0.2
 └── 10.0.0.3

Gateway 自动轮询。


4. 限流

防止接口被刷爆:

1 秒最多 100 请求

例如:

  • 秒杀
  • 登录接口
  • 验证码接口

非常重要。


5. 统一日志

Gateway 可以:

  • 记录请求时间
  • 记录 IP
  • 记录请求参数
  • 记录响应时间

因为所有请求都会经过它。


6. 跨域处理(CORS)

前后端分离里很常见。

很多公司:

  • 不在业务服务处理跨域
  • 而是在 Gateway 统一处理

Reddit 上很多人讨论过这个问题。 (Reddit)


7. 熔断降级

比如:

支付服务挂了

Gateway 可以:

  • 返回默认结果
  • 返回“系统繁忙”
  • 防止整个系统雪崩

四、Gateway 和 Nginx 有什么区别?

很多新人容易混淆。


1.Nginx

更偏:

  • 网络层
  • HTTP服务器
  • 反向代理
  • 静态资源

性能极高。


2.Gateway

更偏:

  • Java代码逻辑
  • Spring生态
  • 微服务治理

它能:

  • 获取 Spring Bean
  • 调用 Redis
  • 校验 JWT
  • 调用数据库
  • 使用过滤器

很多公司:

Nginx
  ↓
Gateway
  ↓
微服务

一起使用。


五、Gateway 底层是什么?

Spring Cloud Gateway:

基于:

  • Spring WebFlux
  • Reactor
  • Netty

构建。 (Spring Cloud)

所以它: 是响应式(Reactive)网关

不是传统 Servlet 模型。


六、Gateway 核心概念

Gateway 最重要三个概念:


1. Route(路由)

决定:

请求转发给谁

例如:

routes:
  - id: user_route
    uri: http://localhost:8081

2. Predicate(断言)

决定:

什么请求匹配这个路由

例如:

predicates:
  - Path=/user/**

表示:

/user/** 才匹配

官方文档里有很多 Predicate: (Spring Cloud)

例如:

  • Path
  • Method
  • Header
  • Cookie
  • Query
  • Host

3. Filter(过滤器)

决定:

请求和响应怎么处理

例如:

  • JWT校验
  • 添加请求头
  • 打日志
  • 修改路径
  • 限流

这是 Gateway 最强大的部分。


七、如何引入 Gateway?

Maven

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

官方也是这样引入。 (Spring Cloud)


八、最简单的 Gateway 示例


假设你有 user、pay 两个微服务,每个微服务有都是多集群的

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 项目

例如:

gateway-server

2. 添加依赖

<dependencies>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

</dependencies>

3. application.yml

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 微服务

例如:

localhost:8081

接口:

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/hello")
    public String hello() {
        return "hello user";
    }
}

5. 启动 pay_route 微服务

例如:

localhost:8082

接口:

@RestController
@RequestMapping("/pay")
public class UserController {

    @GetMapping("/money")
    public String hello() {
        return "pay ok";
    }
}

6. 测试

(1)访问:

http://localhost:9000/user/hello

实际会被 Gateway 转发到 user 微服务:

http://localhost:8081/user/hello

(2)访问:

http://localhost:9000/pay/money

实际会被 Gateway 转发到 pay 微服务:

http://localhost:8082/pay/money

以 访问 http://localhost:9000/user/hello 详细说明:

用户访问:

http://localhost:9000/user/hello

Gateway:

匹配:
Path=/api/user/**

找到

uri: http://localhost:8081

然后去 Nacos 查询:

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 前缀,或者隐藏后端服务的真实接口路径

例如:

/api/user/**
/api/order/**
/api/pay/**

或者:

/api/v1/user/**
/api/v1/order/**
/api/v1/pay/**

这样前端接口风格统一.

但后端服务通常不会写:

@RequestMapping("/api/v1/user")

而是写:

@RequestMapping("/user")

因此需要 Gateway 在转发时把公共前缀删掉。

如何进行配置进行去除前端发送过来的多余的请求前缀呢?

例如:

predicates:
  - Path=/api/user/**
filters:
  - StripPrefix=1

用户请求:

/api/user/hello

Gateway 转发:

/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 ,可以像下面这样写:

predicates:
  - Path=/api/v1/user/**
filters:
  - StripPrefix=2

十、Gateway 过滤器(重点)


1.局部过滤器

只对某个路由生效:

filters:
  - AddRequestHeader=token,123

2.全局过滤器

对所有请求生效:

@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);
    }
}

这就是:

统一登录校验

十一、Gateway + Nacos/Eureka

再企业里通常不会在配置文件中:

uri: http://localhost:8081

企业里通常这样:

uri: lb://user-service

这里:

lb

表示: LoadBalance

Gateway 自动从 Nacos/Eureka 注册中心找到服务。

明明知道 user-service 的 IP,为什么不直接写 IP?

为什么写 lb://user-service

实际上这正是微服务和传统单体应用的重要区别。

1.如果直接写 IP 会怎样?

spring:
  cloud:
    gateway:
      routes:
        - id: user
          uri: http://10.0.0.1:8080
          predicates:
            - Path=/user/**

此时请求流程:

Gateway10.0.0.1:8080

看起来没问题。


但是如果有多个实例:

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 可以吗?

有人会想到:

uri:
  - http://10.0.0.1:8080
  - http://10.0.0.2:8080
  - http://10.0.0.3:8080

问题又来了。

如果:

10.0.0.2 宕机

你必须修改配置:

删除 10.0.0.2

然后重启 Gateway,但是生产环境根本无法接受这样操作。

3.微服务实例是动态变化的

现实情况:

现实情况:

上午:

user-service

10.0.0.1
10.0.0.2
10.0.0.3

中午流量变大:

user-service

10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
10.0.0.5

晚上流量变小:

user-service

10.0.0.1
10.0.0.2

特别是 Kubernetes 环境:

Pod
创建
销毁
重建
迁移

IP 经常变化。

你根本不可能手工维护。

4.服务名才是固定的

虽然 IP 经常变:

10.0.0.1
10.0.0.2
10.0.0.3

但是服务名不变:

user-service

所以注册中心记录:

user-service
    ↓
10.0.0.1

user-service
    ↓
10.0.0.2

user-service
    ↓
10.0.0.3

Gateway 只关心:

lb://user-service

至于具体 IP:

注册中心负责维护

5.lb:// 到底是什么?

这里:

uri: lb://user-service

不是 URL。

而是:

LoadBalancer 协议

意思是:

请通过负载均衡器寻找 user-service

Gateway 看到:

lb://user-service

执行:

1 查询注册中心
2 获取实例列表
3 负载均衡
4 选择一个实例
5 转发请求

6.请求流程

假设:

user-service

10.0.0.1
10.0.0.2
10.0.0.3

用户访问:

GET /user/list

Gateway:

uri: lb://user-service

去 Nacos 查询:

user-service

10.0.0.1
10.0.0.2
10.0.0.3

Spring Cloud LoadBalancer 选择:

10.0.0.2

转发:

http://10.0.0.2:8080/user/list

7.LoadBalancer 是什么?

Spring Cloud 里的:

Spring Cloud LoadBalancer

负责:

从多个实例中选择一个实例

例如:

user-service

10.0.0.1
10.0.0.2
10.0.0.3

LoadBalancer 决定:

本次请求发给谁

8.最常见的负载均衡算法

(1) 轮询(默认)

请求1 → 10.0.0.1
请求2 → 10.0.0.2
请求3 → 10.0.0.3
请求4 → 10.0.0.1

循环。


(2) 随机

请求1 → 10.0.0.3
请求2 → 10.0.0.1
请求3 → 10.0.0.2

随机选择。


(3 ) 权重

假设:

10.0.0.1 权重=5
10.0.0.2 权重=3
10.0.0.3 权重=2

那么:

50%
30%
20%

的流量进入。


9.以前是谁做负载均衡?

老版本 Spring Cloud:

使用的是:

Ribbon

Gateway
 ↓
Ribbon
 ↓
Nacos/Eureka

但是 Ribbon 已经停止维护。


现在:

Gateway
 ↓
Spring Cloud LoadBalancer
 ↓
Nacos/Eureka

官方推荐这个方案。

10.总结

Gateway 中为什么使用 lb://user-service,而不是直接写 IP?

因为微服务实例数量和 IP 是动态变化的,
服务名是固定的。

Gateway 通过 lb:// 服务名访问服务,
再由注册中心返回实例列表,
最后由 Spring Cloud LoadBalancer
按照负载均衡策略选择具体实例。

这样实现了服务发现和负载均衡,
避免了硬编码 IP。

所以在微服务体系里:

Nacos/Eureka/Zookeeper
        ↓
    服务发现

Spring Cloud LoadBalancer
        ↓
    负载均衡

Spring Cloud Gateway
        ↓
    请求路由

十二、Gateway 为什么越来越重要?

现在微服务系统:

  • 服务越来越多
  • 安全越来越复杂
  • 前后端分离越来越普遍

所以: API Gateway 几乎已经是标配

甚至 Kubernetes 环境里很多公司依然使用它。


十三、Gateway 的优点

优点 说明
统一入口 前端只访问一个地址
统一鉴权 JWT统一校验
限流 防止接口被刷
负载均衡 自动分发请求
路由转发 动态转发服务
日志监控 统一处理
熔断降级 提高系统稳定性
与Spring整合 非常方便

十四、Gateway 的缺点

缺点 说明
学习成本高 WebFlux 响应式
调试复杂 异步链路
不适合阻塞代码 不能随便 Thread.sleep
容易成为单点 需要集群部署

十五、企业真实架构

很多公司:

前端
  ↓
Nginx
  ↓
Gateway
  ↓
认证服务
用户服务
订单服务
支付服务

Gateway 常常负责:

  • JWT
  • 限流
  • 灰度发布
  • 黑名单
  • API版本
  • 统一异常处理

十六、需要掌握的重点

必学

  • Gateway 路由
  • Predicate
  • Filter
  • GlobalFilter
  • JWT鉴权
  • Nacos/Eureka整合
  • StripPrefix
  • CORS

进阶

  • 限流
  • 熔断
  • Sentinel
  • Redis令牌桶
  • 灰度发布
  • 链路追踪

高级

  • Reactor
  • WebFlux
  • Mono
  • Flux
  • Netty

十七、学习路线建议

建议顺序:

1. 先学 Gateway 路由
2. 学 Filter
3. 学 JWT 鉴权
4. 学 Nacos 整合
5. 学 限流
6. 学 Sentinel
7. 学 WebFlux

十八、官方学习资源


其他可拓展:

  1. Gateway 完整项目实战
  2. Gateway + JWT 登录鉴权
  3. Gateway + Nacos
  4. Gateway 全局过滤器源码解析
  5. Gateway 底层原理(WebFlux/Reactor)
  6. 企业级 Gateway 架构
  7. Gateway 限流实现
  8. Gateway 与 Nginx 的协作
  9. Gateway 面试题
  10. 从零手写一个微服务网关项目
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐