Skip to content

Route 与 Predicate

This content is not available in your language yet.

路由是 Gateway 的决策对象:predicate 决定“是否接管请求”,URI 和 filters 决定“接管后怎么处理”。配置 DSL 和配置文件最终都收敛到同一套 Route。

先给答案:Route 是“匹配条件 + 过滤计划 + 目标 URI”的不可变请求决策

Section titled “先给答案:Route 是“匹配条件 + 过滤计划 + 目标 URI”的不可变请求决策”

Predicate 只回答请求是否匹配,Filter 负责改写请求或响应,URI 则定义最终转发目标。配置绑定和 Java DSL 最终都要生成同一种 Route,因此运行时不应关心配置来自哪里。

权重路由、路径重写和多个 Predicate 的组合会改变匹配顺序与可观察行为。排查路由错误时按三步走:路由是否加载、Predicate 是否匹配、Filter 是否把请求改成了另一个目标。

RouteDefinition / Java DSL
|
v
RoutePredicateFactory.applyAsync
|
v
AsyncPredicate.and(...)
|
v
RoutePredicateHandlerMapping#lookupRoute
|
v
GATEWAY_ROUTE_ATTR

RouteDefinitionRouteLocator.java:106-111 从 RouteDefinitionLocator 读取定义;131-135 组合 predicate、加载 filters,并用 Route.async(routeDefinition) 构造路由。

RouteDefinitionRouteLocator.java:139-196 通过 GatewayFilterFactory 绑定配置。没有 order 的 filter 会包装成 OrderedGatewayFilter,随后排序;默认 filter 和路由 filter 最终进入同一集合。

RouteDefinitionRouteLocator.java:199-234 查找 predicate 工厂并调用 applyAsync,再用 AsyncPredicate::and 归约。没有 predicate 时在 202-206 返回恒真 predicate。

RouteLocatorBuilder.java:69-82 提供带 id 和自动 id 两种 route 入口,91-92 把 builder 列表转换成 Flux<Route>。PredicateSpec.java:64-70 支持同步 predicate 转异步 predicate;151-194、217-240、308-316 覆盖 method、path、query、weight。

WeightCalculatorWebFilter.java:248-284 为每个 group 生成随机数,并落到规范化权重区间。权重 predicate 再读取选择结果,使同组路由具有单次选择语义。Route.java:279-300 负责把普通 predicate 包装进异步 builder,并在 Route.java:253-259 完成最终构建。

替代方案:匹配路由时动态解析配置并构造 predicate。 为什么不行:请求路径上会重复做绑定、反射和排序,配置错误也延迟到请求时暴露。 证据:RouteDefinitionRouteLocator.java:131-135 预先完成 predicate/filter 构建;请求阶段只执行 route.getPredicate()。

场景 现象 原因 规避
路由顺序不合理 兜底路由吞掉精确路由 lookupRoute 取第一条匹配 精确路由排在通配路由前
predicate 中阻塞 全局延迟升高 异步接口不代表实现非阻塞 predicate 内禁止同步 IO
代理后的 IP 匹配错误 remoteAddr 误判 看到的是代理地址 配置可信 resolver

将外部配置编译成不可变策略对象,运行时只执行策略,是降低热路径复杂度的通用办法,规则引擎和权限决策同样适用。

面试锚点

  • RouteDefinition 怎样编译成 Route?
  • 多个 predicate 是 AND 还是 OR?
  • 权重路由为什么需要 WeightCalculatorWebFilter?