核心契约
这一部分讲 tower 里所有中间件都要遵守、所有调用方都要依赖的那几条约定。源码很少:tower-service 去掉注释只有 52 行,tower-layer 不到 700 行,再加上 tower 里的 builder/mod.rs 和 util 下的几个文件。难的不是代码,而是代码背后那几条编译器检查不了的规则。
- Service trait:
poll_ready的四条规则:Pending时负责唤醒,Ready之后到call之前保持Ready,Ready(Err)表示实例报废,预留的资源在没有call时也要能释放;没就绪就call允许 panic。用ConcurrencyLimit逐条验证,以及&mut S、Box<S>的转发实现。 - Layer 与 Stack:
Layer只是「服务进、服务出」,没有任何约束;Stack<Inner, Outer>先套Inner再套Outer,元组(L1, L2, ...)则是L1在最外层;Identity和layer_fn。 - ServiceBuilder:每次
.layer(x)生成Stack<x, 之前的>,所以先写的在最外层;按 feature 开关的快捷方法;option_layer的Either<T, Identity>;用check_service把类型错误定位到出错的那一层。 - 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 时怎么还。
💬 关联讨论
发起讨论加载中...