Gateway路由配置实战指南(附完整问答)
📖 目录导读
- 为什么需要API网关? – 网关的核心价值与适用场景
- Gateway路由核心概念 – 路由、断言、过滤器的关系
- 手把手写第一个路由 – Spring Cloud Gateway配置步骤
- 路由规则深度解析 – path/host/header/query断言实战
- 过滤器链与自定义扩展 – 请求改写、限流、重试
- 动态路由配置方案 – 从配置文件到数据库+Redis
- 高可用与安全加固 – 跨域、认证、防火墙策略
- 常见问题与问答 – 路由不生效、循环转发、性能调优
为什么需要API网关?
在微服务架构中,服务被拆分为数十个独立模块,客户端直连后端会面临:

- 认证逻辑重复:每个服务都要校验token
- 路由混乱:前端需要维护多个服务地址
- 跨域与安全:无法统一处理CORS和流量控制
网关作为系统唯一入口,承担路由分发、鉴权、限流、日志记录等横切关注点。
Gateway路由核心概念
1 三要素
| 组件 | 作用 | 示例 |
|---|---|---|
| Route(路由) | 定义请求匹配规则与转发目标 | /api/user/** → user-service |
| Predicate(断言) | 判断请求是否符合条件 | 路径、请求头、时间、Cookie |
| Filter(过滤器) | 在请求前后执行增强逻辑 | 添加Header、重写路径、熔断 |
2 工作流程
请求 → Gateway → [断言匹配] → [过滤器链] → 转发目标服务 → 响应返回
手把手写第一个路由
1 环境准备
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2 基础路由配置(application.yml)
spring:
cloud:
gateway:
routes:
- id: user_route # 路由唯一ID
uri: lb://user-service # 负载均衡方式转发
predicates:
- Path=/api/user/** # 匹配 /api/user/ 开头的请求
filters:
- StripPrefix=1 # 去掉第一级路径 /api
测试:访问 http://网关:8080/api/user/info → 转发到 http://user-service/info
路由规则深度解析
1 常用断言(Predicate)
predicates:
# 路径匹配:支持Ant风格通配符
- Path=/api/order/**,/api/payment/{segment}
# 请求头匹配:包含X-Request-Id且值为数字
- Header=X-Request-Id, \d+
# 查询参数匹配:存在token参数
- Query=token
# 请求方法匹配
- Method=GET,POST
# 时间范围:仅允许工作时间访问
- Between=2025-03-01T00:00:00+08:00, 2025-03-31T23:59:59+08:00
2 多条件组合路由
- id: api_v2_route
uri: https://newapi.example.com
predicates:
- Path=/api/v2/**
- Header=Version, 2.0
- RemoteAddr=192.168.1.0/24 # 仅允许内网访问
过滤器链与自定义扩展
1 内置过滤器示例
filters:
# 改写请求路径
- RewritePath=/api/(?<segment>.*), /$\{segment}
# 添加请求头
- AddRequestHeader=Gateway-From, gateway-client
# 设置响应头
- AddResponseHeader=X-Response-Time, ${gateway.timestamp}
# 熔断降级(配合Resilience4j)
- name: CircuitBreaker
args:
name: orderCircuitBreaker
fallbackUri: forward:/fallback/order
2 自定义过滤器(Java代码)
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 校验成功继续转发
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100; // 高优先级
}
}
动态路由配置方案
1 方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 配置文件静态路由 | 简单直观 | 需要重启网关 |
| 数据库+定时刷新 | 实时性中等 | 数据一致性问题 |
| Nacos/Zookeeper配置中心 | 实时生效 | 依赖外部组件 |
| Redis路由缓存 | 高性能、动态 | 需额外开发管理界面 |
2 Nacos动态路由实现
# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
data-id: gateway-routes.yml
group: DEFAULT_GROUP
refresh-enabled: true # 自动刷新
配置中心数据:
spring:
cloud:
gateway:
routes:
- id: dynamic_route
uri: lb://inventory-service
predicates:
- Path=/inventory/**
高可用与安全加固
1 跨域配置
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOriginPatterns: "*" # 生产环境应限定域名
allowedMethods: "*"
allowedHeaders: "*"
allowCredentials: true
2 安全最佳实践
- 禁用Gateway本身端点:
management.endpoints.web.exposure.exclude=gateway - 限制IP白名单:
GatewayFilter+RemoteAddr断言 - 防止重复认证:使用
RequestRateLimiter过滤器做限流 - HTTPS强制跳转:
HttpsRedirectFilter
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route("secure_route", r -> r.path("/api/secure/**")
.filters(f -> f.hystrix(config -> config.setFallbackUri("forward:/fallback")))
.uri("https://secure-backend.com"))
.build();
}
常见问题与问答
❓ Q1:路由配置后访问404
排查步骤:
- 检查断言路径是否正确匹配:
/api/user不等于/api/user/ - 确认服务注册名与
uri中lb://后的名称一致 - 查看网关日志:
DEBUG级别打印路由匹配过程
logging:
level:
org.springframework.cloud.gateway: DEBUG
❓ Q2:网关循环转发
原因:目标服务地址错误写成了网关自身的地址。
解决:检查uri是否指向真实服务,避免使用localhost或0.0.1。
❓ Q3:自定义过滤器不生效
检查点:
- 是否添加
@Component注解 - 是否实现
Ordered接口并设置优先级 - 过滤器顺序值越小越先执行
❓ Q4:如何做到灰度发布?
方案:通过Weight断言实现流量分发
- id: v1_route
uri: lb://service-v1
predicates:
- Path=/api/**
- Weight=service_group, 80 # 80%流量
- id: v2_route
uri: lb://service-v2
predicates:
- Path=/api/**
- Weight=service_group, 20 # 20%流量
❓ Q5:Gateway和Zuul如何选择?
| 对比维度 | Spring Cloud Gateway | Zuul 1.x |
|---|---|---|
| 编程模型 | 响应式(WebFlux) | 同步阻塞(Servlet) |
| 吞吐量 | 更高(异步非阻塞) | 相对较低 |
| 配置灵活性 | 支持Java DSL和YAML | 主要基于Filter |
| 社区活跃度 | 当前主流选择 | 已处于维护模式 |
推荐:新项目直接使用Gateway,低并发旧系统可继续使用Zuul。
如何写出生产级Gateway路由?
- 最小权限原则:限定路径、方法、IP范围
- 统一错误处理:自定义
ErrorWebExceptionHandler - 配置可观测:集成
Micrometer暴露网关指标 - 路由治理:通过配置中心实现动态路由,避免停机重启
- 安全审计:记录所有被拒绝的请求到
ELK日志系统
实践建议:先从YAML静态路由开始,熟悉断言和过滤器后,再迁移到数据库动态路由,遇到路由不匹配时,优先开启DEBUG日志分析断言结果。
问题或补充?欢迎在评论区提出,一起完善网关配置最佳实践。