Spring Cloud Gateway介绍

目录

  • 前言
  • [一、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)
  • [十二、Gateway 为什么越来越重要?](#十二、Gateway 为什么越来越重要?)
  • [十三、Gateway 的优点](#十三、Gateway 的优点)
  • [十四、Gateway 的缺点](#十四、Gateway 的缺点)
  • 十五、企业真实架构
  • 十六、需要掌握的重点
  • 十七、学习路线建议
  • 十八、官方学习资源

前言

Spring Cloud 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 可以结合:

自动找到服务实例。

例如:

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

十八、官方学习资源


其他可拓展:

  1. Gateway 完整项目实战
  2. Gateway + JWT 登录鉴权
  3. Gateway + Nacos
  4. Gateway 全局过滤器源码解析
  5. Gateway 底层原理(WebFlux/Reactor)
  6. 企业级 Gateway 架构
  7. Gateway 限流实现
  8. Gateway 与 Nginx 的协作
  9. Gateway 面试题
  10. 从零手写一个微服务网关项目
相关推荐
逸Y 仙X1 小时前
文章五:Elasticsearch安全通信
java·大数据·安全·elasticsearch·搜索引擎·全文检索·jenkins
quan26312 小时前
20260529,日常开发-查老数据全量更新闭坑
java·mysql·主从·主从延迟
大大杰哥2 小时前
Java 日志框架详解:SLF4J + Logback 从入门到实战
java·开发语言·logback
Dest1ny-安全2 小时前
2026最新CTF知识库:12大Web漏洞深度文章+1156篇历年大赛WP+50+脚本+Payload速查 +AI/RAG离线在线知识库
java·学习·安全·web安全·servlet
404号扳手2 小时前
Java 基础知识(六)
java·后端
我命由我123452 小时前
SEO 与 GEO 极简理解
java·linux·运维·开发语言·学习·算法·运维开发
金銀銅鐵2 小时前
[Java] 自己写程序,来解析方法的 descriptor
java·后端
红辣椒...2 小时前
codex+第三方模型
java·服务器·前端
一个做软件开发的牛马3 小时前
Java 继承与多态:从"是什么"到"能做什么"的设计思维
java·后端