Rust in Everything
基于 tower 0.5.3

核心契约

这一部分讲 tower 里所有中间件都要遵守、所有调用方都要依赖的那几条约定。源码很少:tower-service 去掉注释只有 52 行,tower-layer 不到 700 行,再加上 tower 里的 builder/mod.rs 和 util 下的几个文件。难的不是代码,而是代码背后那几条编译器检查不了的规则。

  1. Service trait:poll_ready 的四条规则:Pending 时负责唤醒,Ready 之后到 call 之前保持 Ready,Ready(Err) 表示实例报废,预留的资源在没有 call 时也要能释放;没就绪就 call 允许 panic。用 ConcurrencyLimit 逐条验证,以及 &mut S、Box<S> 的转发实现。
  2. Layer 与 Stack:Layer 只是「服务进、服务出」,没有任何约束;Stack<Inner, Outer> 先套 Inner 再套 Outer,元组 (L1, L2, ...) 则是 L1 在最外层;Identity 和 layer_fn。
  3. ServiceBuilder:每次 .layer(x) 生成 Stack<x, 之前的>,所以先写的在最外层;按 feature 开关的快捷方法;option_layer 的 Either<T, Identity>;用 check_service 把类型错误定位到出错的那一层。
  4. ServiceExt 与 Oneshot:调用方这一端。ready / ready_oneshot;Oneshot 的 NotReady → Called → Done;call_all 的有序和无序两种队列,以及 poll_ready 出错后怎么收尾。
flowchart TB
  svc["Service:poll_ready + call"] --> layer["Layer:服务进,服务出"]
  layer --> stack["Stack:两层串成一层"]
  stack --> builder["ServiceBuilder:攒 Stack"]
  svc --> ext["ServiceExt:调用方的工具"]
  builder --> mw[04 单服务中间件]
  ext --> mw

第 1 章是全卷的地基。后面每个中间件的 poll_ready 和 call 都可以对照那四条规则来读:它在 poll_ready 里占了什么、存在哪、call 时移到哪、没 call 时怎么还。

💬 关联讨论

发起讨论
加载中...