前言
在微服务架构中,网关是整个系统的'入口门面',负责请求路由、流量控制、权限校验、日志监控等核心功能。Spring Cloud Gateway 作为 Spring 官方推出的第二代网关(替代 Zuul),基于 Netty 非阻塞 IO 模型,具有性能高、功能强、易扩展等优势,完美适配微服务高并发场景。
1. 为什么选择 Spring Cloud Gateway?核心优势与架构原理
1.1 核心优势(对比 Zuul)
性能优异:基于 Netty 响应式编程,非阻塞 IO 模型,吞吐量是 Zuul 1.x 的 3 倍以上
功能强大:原生支持路由、过滤、限流、熔断、重试等核心功能,无需额外集成
易扩展:基于 Spring 生态,支持自定义过滤器、路由断言,适配各种业务场景
无缝整合:与 Spring Cloud Alibaba、Nacos、Sentinel 等组件完美兼容
支持 WebSocket:原生支持 WebSocket 协议,适合实时通信场景(如消息推送)
1.2 核心架构原理
Spring Cloud Gateway 的核心是'路由(Route)+ 断言(Predicate)+ 过滤器(Filter)'的三元组模型:

路由(Route):网关的基本单元,包含 ID、目标 URI、断言集合、过滤器集合
断言(Predicate):路由匹配规则,如路径、方法、参数、Header 等,满足条件则转发
过滤器(Filter):请求 / 响应的拦截器,分全局过滤器(对所有路由生效)和局部过滤器(对指定路由生效)
1.3 核心流程拆解
- 客户端发送请求到 Gateway
- 网关根据断言(Predicate)匹配对应的路由
- 请求经过'前置过滤器链'处理(如鉴权、日志、限流)
- 网关将请求转发到目标微服务
- 微服务返回响应,经过'后置过滤器链'处理(如响应改写、数据加密)
- 网关将最终响应返回给客户端
2. 快速上手:3 步搭建基础网关(附完整配置)
2.1 环境准备
技术栈:SpringBoot 2.7.x + SpringCloud 2021.0.4 + SpringCloud Gateway 3.1.4
注册中心:Nacos 2.2.3(服务发现)
微服务:已部署 user-service、order-service(作为路由目标服务)
2.2 步骤 1:引入核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
注意:Gateway 基于响应式编程,不能引入 spring-boot-starter-web 依赖(会导致 Netty 冲突)
2.3 步骤 2:配置 application.yml
spring:
application:
name: gateway-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=1
server:
port: 8080
management:
endpoints:
2.4 步骤 3:编写启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
}
2.5 测试验证
- 启动 Nacos、user-service、order-service、gateway-service
- 访问网关地址:http://localhost:8080/api/user/get/1 → 转发到 user-service 的/user/get/1 接口
- 访问 http://localhost:8080/api/order/create → 转发到 order-service 的/order/create 接口
- 访问监控端点:http://localhost:8080/actuator/gateway/routes → 查看所有路由配置
3. 路由配置实战:静态路由 + 动态路由(Nacos 适配)
路由是 Gateway 的核心,分为静态路由(配置文件)和动态路由(配置中心),动态路由支持配置热更新,无需重启网关。
3.1 静态路由:多种匹配规则(Predicate)
除了路径匹配,Gateway 支持多种断言规则,可组合使用:
spring:
cloud:
gateway:
routes:
- id: multi-predicate-route
uri: lb://user-service
predicates:
- Path=/api/user/**,/api/member/**
- Method=GET,POST
- Query=userId
- Header=Authorization
- After=2024-01-01T00:00:00+08:00[Asia/Shanghai]
filters:
- StripPrefix=1
3.2 动态路由:基于 Nacos 实现热更新
静态路由修改后需重启网关,生产环境推荐使用动态路由,通过 Nacos 配置中心实现配置实时刷新。
3.2.1 引入 Nacos 配置依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
3.2.2 配置 bootstrap.yml(优先级高于 application.yml)
spring:
application:
name: gateway-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
group: DEFAULT_GROUP
discovery:
server-addr: 127.0.0.1:8848
3.2.3 在 Nacos 中创建配置
- 登录 Nacos 控制台 → 配置管理 → 配置列表 → 新建
- 配置信息:
- 数据 ID:gateway-service.yaml(服务名 + 文件格式)
- 分组:DEFAULT_GROUP
- 配置内容(路由配置):
spring:
cloud:
gateway:
routes:
- id: dynamic-user-route
uri: lb://user-service
predicates:
- Path=/dynamic/user/**
filters:
- StripPrefix=1
- id: dynamic-order-route
uri: lb://order-service
predicates:
- Path=/dynamic/order/**
filters:
- StripPrefix=1
3.2.4 编写动态路由配置类
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
@Configuration
public class DynamicRouteConfig {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private NacosConfigProperties nacosConfigProperties;
private static final String DATA_ID = "gateway-service.yaml";
private static final String GROUP = "DEFAULT_GROUP";
@PostConstruct
NacosException {
();
properties.put(, nacosConfigProperties.getServerAddr());
NacosFactory.createConfigService(properties);
configService.getConfig(DATA_ID, GROUP, );
updateRoute(configInfo);
configService.addListener(DATA_ID, GROUP, () {
Executor {
;
}
{
updateRoute(configInfo);
}
});
}
{
JSON.parseObject(configInfo, GatewayConfig.class);
List<RouteDefinition> routeDefinitions = gatewayConfig.getSpring().getCloud().getGateway().getRoutes();
routeDefinitions.forEach(route -> {
routeDefinitionWriter.delete(Mono.just(route.getId())).subscribe();
});
routeDefinitions.forEach(route -> {
routeDefinitionWriter.save(Mono.just(route)).subscribe();
});
}
{
Spring spring;
Spring {
spring;
}
{
.spring = spring;
}
{
Cloud cloud;
Cloud {
cloud;
}
{
.cloud = cloud;
}
}
{
Gateway gateway;
Gateway {
gateway;
}
{
.gateway = gateway;
}
}
{
List<RouteDefinition> routes;
List<RouteDefinition> {
routes;
}
{
.routes = routes;
}
}
}
}
3.2.5 测试动态路由
- 修改 Nacos 中的路由配置(如添加新路由、修改路径匹配规则)
- 无需重启网关,访问新路由地址 → 直接生效
- 访问 http://localhost:8080/actuator/gateway/routes → 查看更新后的路由
4. 过滤器开发:全局过滤器 + 局部过滤器(含实战案例)
Gateway 的过滤器分为全局过滤器(对所有路由生效)和局部过滤器(仅对指定路由生效),核心作用是对请求 / 响应进行拦截增强。
4.1 过滤器执行顺序

前置过滤器(Pre):请求转发前执行(如鉴权、日志、参数改写)
后置过滤器(Post):响应返回前执行(如响应加密、数据格式化)
4.2 全局过滤器实战:3 个高频场景
4.2.1 场景 1:全局日志打印(记录请求响应)
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
@Configuration
public class GlobalLogFilterConfig {
@Bean
@Order(-100)
public GlobalFilter logFilter() {
return (exchange, chain) -> {
String path = exchange.getRequest().getPath().value();
String method = exchange.getRequest().getMethod().name();
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
System.out.printf("[%s] 收到请求:IP=%s, 方法=%s, 路径=%s%n", LocalDateTime.now(), ip, method, path);
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
int statusCode = exchange.getResponse().getStatusCode().value();
System.out.printf("[%s] 响应结果:状态码=%s, 路径=%s%n", LocalDateTime.now(), statusCode, path);
}));
};
}
}
4.2.2 场景 2:全局跨域处理(解决前后端跨域)
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Mono;
@Configuration
public class GlobalCorsFilterConfig {
@Bean
@Order(-101)
public GlobalFilter corsFilter() {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
response.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
response.getHeaders().add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,DELETE,OPTIONS");
response.getHeaders().add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
chain.filter(exchange);
};
}
}
4.2.3 场景 3:全局鉴权过滤器(JWT Token 验证)
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class GlobalAuthFilterConfig {
private static final List<String> WHITE_LIST = new ArrayList<>();
static {
WHITE_LIST.add("/api/user/login");
WHITE_LIST.add("/api/user/register");
WHITE_LIST.add("/actuator/**");
}
private static final String JWT_SECRET = "your-secret-key-32bytes-long-123456";
private final SecretKey secretKey = Keys.hmacShaKeyFor(JWT_SECRET.getBytes(StandardCharsets.UTF_8));
@Bean
@Order(-99)
GlobalFilter {
(exchange, chain) -> {
exchange.getRequest().getPath().value();
(WHITE_LIST.stream().anyMatch(path::startsWith)) {
chain.filter(exchange);
}
exchange.getRequest().getHeaders().getFirst();
(!StringUtils.hasText(token) || !token.startsWith()) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
exchange.getResponse().setComplete();
}
token = token.substring();
{
Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(token)
.getBody();
claims.get(, String.class);
exchange.getRequest().mutate()
.header(, userId)
.build();
chain.filter(exchange.mutate().request(request).build());
} (Exception e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
exchange.getResponse().setComplete();
}
};
}
}
4.3 局部过滤器实战:请求改写与响应处理
局部过滤器仅对指定路由生效,需实现 GatewayFilter 接口:
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class AddParamGatewayFilterFactory extends AbstractGatewayFilterFactory<AddParamGatewayFilterFactory.Config> {
public static class Config {
private String paramName;
private String paramValue;
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public String getParamValue() {
return paramValue;
}
public void setParamValue(String paramValue) {
this.paramValue = paramValue;
}
}
public AddParamGatewayFilterFactory() {
super(Config.class);
}
List<String> {
Arrays.asList(, );
}
GatewayFilter {
(exchange, chain) -> {
exchange.getRequest().mutate()
.queryParam(config.getParamName(), config.getParamValue())
.build();
chain.filter(exchange.mutate().request(request).build());
};
}
}
局部过滤器使用(在路由中配置)
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
- AddParam=version,v1.0
5. 限流鉴权核心实现:基于 Redis 的限流 + JWT 鉴权
5.1 限流实现:基于 Redis 的令牌桶算法
Gateway 自带限流过滤器 RequestRateLimiter,结合 Redis 可实现分布式限流(支持 IP、用户 ID、接口等维度)。
5.1.1 引入 Redis 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
5.1.2 配置 Redis 与限流规则
spring:
redis:
host: 127.0.0.1
port: 6379
password:
database: 0
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: 0.5
redis-rate-limiter.burstCapacity: 5
key-resolver: "#{@ipKeyResolver}"
5.1.3 自定义限流 Key 解析器
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class RateLimitKeyResolverConfig {
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> {
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
return Mono.just(ip);
};
}
@Bean
public KeyResolver userIdKeyResolver() {
return exchange -> {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
return Mono.just(userId != null ? userId : ipKeyResolver().resolve(exchange).block());
};
}
@Bean
public KeyResolver pathKeyResolver() {
return exchange -> {
String path = exchange.getRequest().getPath().value();
return Mono.just(path);
};
}
}
5.1.4 限流效果测试
- 10 秒内多次访问 http://localhost:8080/api/user/get/1
- 超过 5 次后,网关返回 429 Too Many Requests
- Redis 中会生成限流相关 Key(如 request_rate_limiter.{IP}.timestamp)
5.2 鉴权完整流程:JWT + 权限校验
5.2.1 JWT 生成(用户登录接口)
在 user-service 中实现登录接口,生成 JWT Token:
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
@RestController
@RequestMapping("/user")
public class UserController {
private static final String JWT_SECRET = "your-secret-key-32bytes-long-123456";
private final SecretKey secretKey = Keys.hmacShaKeyFor(JWT_SECRET.getBytes(StandardCharsets.UTF_8));
private static final long EXPIRATION = 3600000;
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
if ("admin".equals(username) && "123456".equals(password)) {
String token = Jwts.builder()
.setSubject(username)
.claim(, )
.claim(, )
.setExpiration( (System.currentTimeMillis() + EXPIRATION))
.signWith(secretKey)
.compact();
+ token;
}
;
}
}
5.2.2 权限校验(基于角色)
在全局鉴权过滤器中扩展角色校验:
String role = claims.get("role", String.class);
if (path.startsWith("/api/admin") && !"ADMIN".equals(role)) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
6. 生产环境优化:性能调优 + 熔断降级 + 监控告警
6.1 性能调优配置
spring:
cloud:
gateway:
httpclient:
pool:
max-idle-time: 60000
max-connections: 1000
max-pending-connections: 500
connect-timeout: 3000
response-timeout: 5000
threads:
worker: 200
server:
port: 8080
netty:
connection-timeout: 2000
threads:
worker: 200
6.2 熔断降级(整合 Sentinel)
避免下游服务故障导致网关阻塞,通过 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>
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
scg:
fallback:
mode: response
response-status: 503
response-body: '{"code":503,"message":"服务繁忙,请稍后再试"}'
6.3 监控告警
暴露 Actuator 端点,结合 Prometheus+Grafana 监控路由命中率、响应时间、限流次数
配置 Sentinel 告警规则,服务异常时通过邮件 / 钉钉通知运维
7. 高频场景配置模板(直接复制使用)
模板 1:静态路由完整配置
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/user/**
- Method=GET,POST
- Header=Authorization
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 10
key-resolver: "#{@ipKeyResolver}"
模板 2:跨域配置(全局)
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowed-origins: "*"
allowed-methods: "*"
allowed-headers: "*"
allow-credentials: true
max-age: 3600
模板 3:Redis 限流配置(基于用户 ID)
spring:
cloud:
gateway:
routes:
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 2
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userIdKeyResolver}"
模板 4:熔断降级配置(Sentinel)
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:8080
scg:
fallback:
mode: redirect
redirect: /error.html
8. 实战避坑指南(10 个实测踩坑总结)
- 依赖冲突:引入 spring-boot-starter-web 导致 Netty 冲突,需删除该依赖
- 跨域配置失效:同时配置了全局 CorsFilter 和 globalcors,优先级冲突,选择一种即可
- 动态路由不生效:Nacos 配置的 dataId 与 bootstrap.yml 不一致,或路由 ID 重复
- 限流不生效:未引入 spring-boot-starter-data-redis-reactive 依赖,或 Redis 连接失败
- Token 传递丢失:多线程环境下 RequestContextHolder 获取不到请求,需手动传递 ThreadLocal
- 路由匹配优先级:路由配置顺序即匹配优先级,精确路径路由应放在前面
- StripPrefix 失效:路径匹配规则与 StripPrefix 级数不匹配(如/api/user/**对应 StripPrefix=1)
- 响应超时配置无效:需同时配置 Gateway 的 httpclient.response-timeout 和微服务的超时时间
- Sentinel 熔断不生效:未引入 spring-cloud-alibaba-sentinel-gateway 依赖
- 日志打印乱码:Netty 默认编码为 ISO-8859-1,需配置 JVM 参数-Dfile.encoding=UTF-8
9. 面试高频考点梳理
- Spring Cloud Gateway 的核心组件?(路由、断言、过滤器)
- Gateway 与 Zuul 的区别?(性能、模型、功能支持)
- Gateway 的过滤器执行顺序?(全局→局部,前置→后置,Order 值越小优先级越高)
- 如何实现动态路由?(基于 Nacos 配置中心 + RouteDefinitionWriter)
- Gateway 的限流算法是什么?(令牌桶算法,基于 Redis 实现分布式限流)
- 如何解决 Gateway 的跨域问题?(全局 CorsFilter 或 globalcors 配置)
- Gateway 如何实现鉴权?(全局过滤器 + JWT Token 验证)
- Gateway 的性能优化手段?(连接池配置、线程数调整、压缩、缓存)
10. 总结与展望
Spring Cloud Gateway 作为微服务架构的核心网关,凭借其高性能、强扩展性、丰富的功能,成为企业级微服务项目的首选。本文从基础搭建到生产落地,覆盖了路由、过滤、限流、鉴权等核心场景,提供的配置模板和避坑指南可直接应用于实际项目。
后续可进一步探索 Gateway 的高级特性,如:
灰度发布(基于权重路由)
分布式链路追踪(整合 SkyWalking/Zipkin)
网关层数据脱敏
自定义路由断言工厂