4. 网关路由配置:静态路由与动态路由
路由配置,说白了就是告诉网关:「这个请求该往哪儿送」。我见过不少团队,网关配得乱七八糟,结果线上出了故障,查半天发现是路由写错了。嗯,今天咱们就把这块彻底聊透。
4.1 静态路由 vs 动态路由
先搞清楚这两个概念。静态路由,就是你在配置文件里一条一条写死的路由规则。动态路由,则是通过注册中心、配置中心自动发现和更新的路由。
| 对比维度 | 静态路由 | 动态路由 |
|---|---|---|
| 配置方式 | YAML / 配置文件硬编码 | 注册中心 / 配置中心动态下发 |
| 变更生效 | 需重启网关或重新加载 | 实时生效,无需重启 |
| 适用场景 | 测试环境、固定后端、小规模 | 生产环境、微服务架构、大规模 |
| 维护成本 | 低(规则少时) | 中(需维护注册中心) |
| 故障恢复 | 手动修改配置 | 自动摘除故障节点 |
我的建议:开发环境用静态路由,简单直接。生产环境必须上动态路由。我曾经见过一个项目,生产用了静态路由,后端服务扩缩容时网关完全不知道,结果一半请求都报 502。那场面,真是惨不忍睹。
4.2 路由规则定义
路由规则,核心就三要素:路由 ID、断言条件、目标 URI。拿 Spring Cloud Gateway 举例,一个典型的路由配置长这样:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
- AddRequestHeader=X-Request-Source, gateway
这里我解释一下每个字段:
- id:路由的唯一标识,方便日志排查和监控
- uri:目标地址,可以是
http://固定地址,也可以是lb://负载均衡地址 - predicates:断言条件,决定「什么请求匹配这条路由」
- filters:过滤器,对请求/响应做加工处理
避坑指南:路由 ID 一定要有业务含义。我曾经接手过一个项目,路由 ID 全是 route-1、route-2 这种,排查问题时根本不知道哪个路由对应哪个服务。后来我花了整整两天才理清楚。记住,命名规范是给未来的自己看的。
4.3 断言工厂
断言工厂,就是用来匹配请求条件的。网关内置了很多好用的断言工厂,我挑几个最常用的说说:
| 断言工厂 | 作用 | 示例 |
|---|---|---|
| Path | 匹配请求路径 | - Path=/api/order/** |
| Method | 匹配 HTTP 方法 | - Method=GET,POST |
| Header | 匹配请求头 | - Header=X-Token, \d+ |
| Query | 匹配查询参数 | - Query=version, v1 |
| Cookie | 匹配 Cookie | - Cookie=sessionId, .* |
| Host | 匹配域名 | - Host=**.example.com |
| RemoteAddr | 匹配客户端 IP | - RemoteAddr=192.168.1.0/24 |
你想想看,这些断言工厂可以组合使用。比如:
predicates:
- Path=/api/admin/**
- Method=POST
- Header=X-Admin-Token, .+
- RemoteAddr=10.0.0.0/8
这个配置的意思是:只有来自内网、携带管理员 Token 的 POST 请求,才能访问管理后台接口。多一层断言,就多一层安全。
注意:多个断言之间是 AND 关系,必须全部满足才算匹配成功。如果你想实现 OR 逻辑,需要配置多条路由。我见过有人在这里踩坑,以为断言是 OR 关系,结果调试了半天。
4.4 过滤器工厂
过滤器工厂,负责对请求和响应做「加工」。我个人习惯把过滤器分成三类:
- 请求预处理:添加/修改请求头、参数、路径重写
- 响应后处理:添加/修改响应头、响应体修改
- 安全与限流:鉴权、限流、熔断
常用的过滤器工厂:
| 过滤器工厂 | 作用 | 配置示例 |
|---|---|---|
| StripPrefix | 去除路径前缀 | - StripPrefix=1 |
| AddRequestHeader | 添加请求头 | - AddRequestHeader=X-Gateway, true |
| AddResponseHeader | 添加响应头 | - AddResponseHeader=X-Powered-By, Gateway |
| RewritePath | 路径重写 | - RewritePath=/api/(?<seg>.*), /$\{seg} |
| RequestRateLimiter | 请求限流 | - name: RequestRateLimiter |
| Retry | 请求重试 | - name: Retry |
| CircuitBreaker | 熔断降级 | - name: CircuitBreaker |
举个例子,假设你的后端服务接口是 /user/list,但前端请求的是 /api/user/list。这时候就需要 StripPrefix=1 把 /api 去掉。我刚开始做网关时,忘了配这个,结果后端一直报 404,查了半天才发现是路径没对齐。
4.5 路由配置的核心流程
说了这么多,咱们用一张图把整个流程串起来:
核心要点:路由匹配是「短路」机制。一旦某个路由的断言全部匹配成功,网关就会立即执行该路由的过滤器链,然后转发请求,不再检查后续路由。所以路由的顺序很重要——精确匹配的放前面,模糊匹配的放后面。
4.6 实战经验总结
最后,分享几个我在项目中积累的经验:
- 路由顺序很重要:精确路由放前面,通配路由放后面。比如
/api/user/detail要放在/api/user/**前面。 - 断言越精确越好:能用 Path+Method 就别只用 Path。多一层断言,少一分误匹配。
- 过滤器顺序有讲究:先做鉴权,再做限流,最后做路径重写。顺序错了,可能鉴权还没做,请求就被限流了。
- 动态路由一定要做健康检查:我曾经遇到过注册中心里的服务已经挂了,但网关还在往那里转发。加上健康检查,自动摘除故障节点,能省很多事。
小技巧:调试路由时,可以开启网关的日志级别:logging.level.org.springframework.cloud.gateway=DEBUG。这样每次请求匹配了哪条路由、执行了哪些过滤器,都能看得一清二楚。这招帮我解决过不少疑难杂症。