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 路由配置的核心流程

说了这么多,咱们用一张图把整个流程串起来:

路由配置核心流程 客户端请求 断言工厂匹配 Path / Method / Header / Query / Cookie 匹配成功 → 执行过滤器链 匹配失败 → 返回 404 过滤器链处理 StripPrefix / AddHeader / RateLimit 转发到目标服务 lb://user-service 路由匹配是「短路」机制:一旦匹配成功,后续路由不再检查

核心要点:路由匹配是「短路」机制。一旦某个路由的断言全部匹配成功,网关就会立即执行该路由的过滤器链,然后转发请求,不再检查后续路由。所以路由的顺序很重要——精确匹配的放前面,模糊匹配的放后面。

4.6 实战经验总结

最后,分享几个我在项目中积累的经验:

  1. 路由顺序很重要:精确路由放前面,通配路由放后面。比如 /api/user/detail 要放在 /api/user/** 前面。
  2. 断言越精确越好:能用 Path+Method 就别只用 Path。多一层断言,少一分误匹配。
  3. 过滤器顺序有讲究:先做鉴权,再做限流,最后做路径重写。顺序错了,可能鉴权还没做,请求就被限流了。
  4. 动态路由一定要做健康检查:我曾经遇到过注册中心里的服务已经挂了,但网关还在往那里转发。加上健康检查,自动摘除故障节点,能省很多事。

小技巧:调试路由时,可以开启网关的日志级别:logging.level.org.springframework.cloud.gateway=DEBUG。这样每次请求匹配了哪条路由、执行了哪些过滤器,都能看得一清二楚。这招帮我解决过不少疑难杂症。