路由与状态共享
This content is not available in your language yet.
Axum 路由由两级分派组成:先用 matchit 匹配路径,再由 MethodRouter 匹配 HTTP method。Router<S> 的 S 表示“仍缺少、需要在运行前提供的状态”。
先给答案:Axum 路由由两级分派组成:先用 matchit 匹配路径,再由 MethodRouter 匹配 HTT…
Section titled “先给答案:Axum 路由由两级分派组成:先用 matchit 匹配路径,再由 MethodRouter 匹配 HTT…”Axum 路由由两级分派组成:先用 matchit 匹配路径,再由 MethodRouter 匹配 HTTP method。Router<S 的 S 表示“仍缺少、需要在运行前提供的状态”。 正文沿“两级路由 -> route、nest、merge -> “缺失状态”模型”展开:先确认入口和状态归属,再跟踪控制流或数据流的推进,最后落到对外可观察的结果。
主要失效边界集中在“重复注册同 path+method、nest 后 URI 认知错误、状态被多层 Arc<Mutex< 包裹”这些场景。它们破坏的是容量、顺序、并发或生命周期前提;排查时应先确认状态是否仍由正确对象持有,再核对推进条件和清理路径。
URI path -> PathRouter / matchit::Router<RouteId> -> 写入 URL params 与 MatchedPath -> Endpoint::MethodRouter -> MethodRouter 按 GET/POST/... 选择 Route -> fallback / 405Router<S> 保存 path_router、fallback_router、default_fallback 与 v0.7 checks 标记(axum/src/routing/mod.rs:86-94)。PathRouter 的内部匹配器包装在 routing/path_router.rs:404-432,调用入口在 path_router.rs:325-372。MethodRouter 定义在 routing/method_routing.rs:549-558,实际 method 分派在 method_routing.rs:1200-1251。
route、nest、merge
Section titled “route、nest、merge”Router::route把MethodRouter插入路径树(routing/mod.rs:192-205)。Router::nest同时处理路径前缀、fallback 与 nested path extensions(routing/mod.rs:220-249)。Router::merge合并两棵路由树,并检查 fallback 冲突(routing/mod.rs:250-301)。MethodRouter::merge合并 method endpoint,重复 method 会 panic(routing/method_routing.rs:1171-1198)。
“缺失状态”模型
Section titled ““缺失状态”模型”Router<S> 不是“已经持有 S”,而是“还需要一个 S”。调用 with_state(state: S) 后返回 Router<S2>(routing/mod.rs:444-450);通常让 S2 = (),此时 Router 才能直接作为 Service 或交给 serve。State<T> extractor 定义在 extract/state.rs:301,借助 FromRef<S> 从应用状态投影子状态(extract/state.rs:304-324)。
Router<AppState> --with_state(app_state)--> Router<()> 缺状态 可运行为什么状态类型表达“缺少”而不是“拥有”
Section titled “为什么状态类型表达“缺少”而不是“拥有””替代方案:Router<S> 永远表示内部已经存有 S。
为什么不行:路由组合时很难区分“构建模板”和“可运行服务”,嵌套路由也容易过早固定状态。
证据:with_state<S2> 消费当前缺失类型并返回新的缺失类型(routing/mod.rs:444);只有 Router<()> 的 Service/make-service 路径最自然。
fallback 语义
Section titled “fallback 语义”404 与 405 分开:路径没匹配走 Router fallback;路径存在但 method 不匹配走 MethodRouter fallback。default_fallback 标记用于 merge 时判断用户是否已自定义 fallback,避免静默覆盖。
| 场景 | 现象 | 原因 | 规避 |
|---|---|---|---|
| 重复注册同 path+method | 构建期 panic | 路由冲突无法确定优先级 | 集中路由表并写启动测试 |
| nest 后 URI 认知错误 | middleware 看到的路径不同 | nested path 会写扩展并剥前缀 | 使用 OriginalUri / NestedPath 明确语义 |
状态被多层 Arc<Mutex<_>> 包裹 |
锁粒度失控 | 把整个应用状态当共享可变对象 | 按领域拆 state,内部选并发结构 |
| fallback 被 merge 覆盖或冲突 | panic 或响应变化 | 两棵树都定义自有 fallback | merge 前约定唯一所有者 |
路由树与 method 表分层,可把路径匹配算法和 HTTP 语义解耦;用类型参数表示“尚未满足的构建依赖”,则可在编译期区分 builder 与 runnable object。
面试锚点
- Axum 为什么要做路径与 method 两级路由?
Router<S>中的 S 为什么是 missing state?- 404 fallback 与 405 fallback 有什么不同?