Spring Gateway 全面解析:从入门到进阶实践
在微服务架构盛行的当下,API 网关作为系统的 “入口门面”,承担着路由转发、负载均衡、权限认证、限流熔断等关键职责。Spring Cloud 生态中,Spring Gateway 凭借其非阻塞、高性能的特性,逐渐取代 Zuul 成为主流的 API 网关选择。本文将从基础概念出发,逐步深入到实战配置与进阶技巧,帮助开发者快速掌握 Spring Gateway 的核心能力。
一、Spring Gateway 是什么?
Spring Gateway 是 Spring Cloud 官方推出的第二代网关产品,基于 Spring 5、Spring Boot 2 和 Project Reactor 构建,采用非阻塞异步模型,能有效应对高并发场景。它并非简单的请求转发工具,而是集路由、过滤、熔断、限流等功能于一体的企业级网关解决方案。
核心优势
- 非阻塞高性能:基于 Netty 实现异步 I/O,吞吐量远高于传统的 Zuul 1.x(同步阻塞模型);
- 原生 Spring 生态:无缝集成 Spring Boot、Spring Security 等组件,配置简单且易于扩展;
- 功能全面:内置路由转发、负载均衡、熔断降级、请求过滤、限流、路径重写等核心能力;
- 动态配置:支持通过配置中心(如 Nacos、Apollo)实现路由规则的动态刷新,无需重启服务;
- 响应式编程:基于 Reactor 模型,可轻松处理异步流数据,适配微服务的分布式场景。
二、核心概念与工作原理
在使用 Spring Gateway 前,必须先理解其 3 个核心组件,这是后续配置和开发的基础。
1. 核心组件
组件 | 作用说明 |
Route(路由) | 网关的基本单元,由 “ID + 目标 URI + 断言集合 + 过滤器集合” 组成,是请求转发的规则定义; |
Predicate(断言) | 本质是 “条件判断逻辑”,用于匹配请求的 URL、方法、请求头、参数等,满足则执行路由; |
Filter(过滤器) | 用于修改请求或响应,分为 “前置过滤器”(请求转发前执行)和 “后置过滤器”(响应返回前执行),支持全局或路由级配置; |
2. 工作流程
Spring Gateway 的请求处理流程可概括为以下 4 步,核心是 “断言匹配路由 + 过滤器链式处理”:
- 请求进入网关:客户端请求首先到达 Gateway 的 Netty 服务器;
- 断言匹配路由:网关根据配置的 Predicate 规则,匹配对应的 Route(若未匹配则返回 404);
- 过滤器链式执行:
- 执行当前 Route 的 “前置过滤器”(如修改请求头、鉴权);
- 转发请求到目标微服务;
- 执行 “后置过滤器”(如修改响应体、添加响应头);
4.返回响应结果:将处理后的响应返回给客户端。
三、入门实战:快速搭建 Spring Gateway
下面通过一个简单案例,演示如何搭建 Spring Gateway 并实现基础路由转发。
1. 环境准备
- JDK 11+(Spring Gateway 基于 Spring 5,需 JDK 8 以上,推荐 11);
- Spring Boot 2.7.x(需与 Spring Cloud 版本匹配,本文使用 Spring Cloud Alibaba 2021.0.4.0);
- 一个目标微服务(如 user-service,端口 8081,提供/api/user/get接口)。
2. 搭建网关工程
步骤 1:引入依赖
在 Spring Boot 项目的pom.xml中添加 Spring Gateway 核心依赖(无需引入 web 依赖,Gateway 基于 Netty,与 Spring MVC 冲突):
<dependencies>
<!-- Spring Gateway核心依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 服务发现依赖(若需从Nacos/Eureka获取服务,可选) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<!-- Spring Cloud Alibaba版本管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
步骤 2:配置路由规则
在application.yml中配置网关端口和路由规则(支持两种路由方式:直接指定 URI、通过服务名转发):
application:
name: gateway-service # 网关服务名
cloud:
# Nacos服务发现配置(若使用服务名转发,需配置)
nacos:
discovery:
server-addr: 127.0.0.1:8848
# Gateway核心配置
gateway:
routes:
# 路由1:通过服务名转发到user-service(需配合服务发现)
- id: user-service-route # 路由唯一ID(自定义,不重复即可)
uri: lb://user-service # lb://表示负载均衡,后面跟服务名
predicates:
- Path=/api/user/** # 断言:匹配路径以/api/user/开头的请求
filters:
- StripPrefix=1 # 过滤器:去掉路径的第1级(如/api/user/get → /user/get)
# 路由2:直接指定URI转发(适用于非微服务场景)
- id: direct-route
uri: http://127.0.0.1:8081 # 目标服务地址
predicates:
- Path=/direct/user/** # 匹配路径以/direct/user/开头的请求
- Method=GET # 额外断言:只匹配GET请求
filters:
- StripPrefix=1 # 去掉路径第1级(/direct/user/get → /user/get)
步骤 3:启动网关服务
创建启动类(无需添加@EnableWebMvc或@EnableWebFlux,Gateway 自动配置):
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现(若使用Nacos/Eureka,需添加)
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
步骤 4:测试路由转发
- 启动 user-service(端口 8081)和 gateway-service(端口 8080);
- 访问网关路由 1:http://127.0.0.1:8080/api/user/get → 网关会转发到http://user-service/user/get;
- 访问网关路由 2:http://127.0.0.1:8080/direct/user/get → 网关会转发到http://127.0.0.1:8081/user/get。
四、进阶实践:核心功能配置
除了基础路由,Spring Gateway 的限流、熔断、全局过滤等功能是生产环境的核心需求,下面逐一讲解配置方式。
1. 限流配置(基于 Redis)
Spring Gateway 内置了基于 Redis 的限流过滤器(RequestRateLimiter),支持按 IP、用户 ID 等维度限流。
步骤 1:引入 Redis 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
步骤 2:配置限流规则
在application.yml的路由过滤器中添加限流配置:
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
# 限流过滤器
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒允许的令牌数(平均速率)
redis-rate-limiter.burstCapacity: 20 # 令牌桶最大容量(峰值速率)
key-resolver: "#{@ipKeyResolver}" # 限流维度(这里是IP,需自定义Bean)
# Redis配置
redis:
host: 127.0.0.1
port: 6379
password: 123456
步骤 3:自定义限流维度 Bean
创建KeyResolver的实现类,定义限流维度(如 IP、用户 ID):
@Configuration
public class RateLimitConfig {
/**
* 基于IP的限流维度
*/
@Bean("ipKeyResolver")
public KeyResolver ipKeyResolver() {
return exchange -> {
// 获取客户端IP
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
return Mono.just(ip); // 返回IP作为限流Key
};
}
/**
* 基于用户ID的限流维度(若有用户认证,可替换)
*/
// @Bean("userIdKeyResolver")
// public KeyResolver userIdKeyResolver() {
// return exchange -> {
// String userId = exchange.getRequest().getHeaders().getFirst("X-User-ID");
// return Mono.justOrEmpty(userId).defaultIfEmpty("anonymous");
// };
// }
}
2. 熔断降级(集成 Sentinel)
在微服务场景中,若目标服务故障,网关需要快速熔断并返回友好提示,避免级联失败。Spring Gateway 可集成 Sentinel 实现熔断降级。
步骤 1:引入 Sentinel 依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
步骤 2:配置熔断规则
在application.yml中添加 Sentinel 配置:
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080 # Sentinel控制台地址
scg:
fallback:
mode: response # 熔断降级模式(response:返回自定义响应;redirect:重定向)
response-body: "{\"code\":503,\"message\":\"服务暂时不可用,请稍后再试\"}" # 自定义响应体
response-status: 503 # 响应状态码
步骤 3:在 Sentinel 控制台配置熔断规则
- 启动 Sentinel 控制台(下载 jar 包后执行java -jar sentinel-dashboard-1.8.6.jar);
- 访问控制台(http://127.0.0.1:8080,默认账号密码 sentinel);
- 在 “网关熔断” 菜单中,为user-service-route路由配置熔断规则(如 “慢调用比例”:慢调用阈值 1000ms,比例阈值 0.5,熔断时长 5s)。
3. 全局过滤器(统一鉴权)
全局过滤器会对所有路由生效,适合实现统一鉴权、日志记录等功能。下面实现一个 “Token 鉴权” 的全局过滤器。
自定义全局过滤器
@Bean
@Order(1)
public GlobalFilter authFilter() {
return (exchange, chain) -> {
// 1. 排除不需要鉴权的路径(如登录接口)
String path = exchange.getRequest().getURI().getPath();
if (path.contains("/api/user/login")) {
return chain.filter(exchange); // 直接放行
}
// 2. 获取请求头中的Token
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
// 3. 鉴权逻辑(实际场景需校验Token有效性,如解析JWT)
if (token == null || !token.startsWith("Bearer ")) {
// 鉴权失败:返回401未授权
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 4. 鉴权通过:继续执行后续过滤器
return chain.filter(exchange);
};
}
}
五、常见问题与解决方案
1.Gateway 与 Spring MVC 冲突
问题:引入spring-boot-starter-web依赖后,网关启动失败。
原因:Gateway 基于 Spring WebFlux,与 Spring MVC(spring-boot-starter-web)冲突。
解决方案:删除spring-boot-starter-web依赖,仅保留spring-cloud-starter-gateway。
2.路由规则不生效
问题:配置路由后,请求无法转发到目标服务。
排查方向:
- 检查路由的predicates规则是否匹配请求路径(如路径是否带斜杠);
- 若使用服务名转发(lb://xxx),确认服务已注册到 Nacos/Eureka,且网关已开启服务发现;
- 检查过滤器是否正确配置(如StripPrefix是否多删或少删路径层级)。
3.限流不生效
问题:配置 Redis 限流后,请求未被限流。
排查方向:
- 确认 Redis 服务正常,且网关能连接到 Redis;
- 检查KeyResolverBean 是否正确注入(Bean 名称与配置中的key-resolver一致);
- 查看 Redis 中是否生成了限流相关的 Key(如rate.limiters.{routeId}.{key})。
六、总结
Spring Gateway 作为 Spring Cloud 生态的核心网关组件,凭借其非阻塞高性能、丰富的功能和易扩展性,成为微服务架构的首选网关方案。本文从基础概念、搭建实战到进阶功能(限流、熔断、全局过滤)进行了全面讲解,开发者可根据实际业务需求,灵活配置路由规则和过滤器,构建稳定、高效的 API 网关层。
后续可进一步探索 Spring Gateway 的高级特性,如动态路由(基于 Nacos/Apollo 配置中心)、自定义断言、响应式过滤器开发等,以满足更复杂的业务场景。