util:组合子
tower::util 由 util feature 打开,这一部分讲其中的「胶水」:它们自己不占资源、不限流,只负责把服务造出来、接起来、改个形状。读它们仍然问两个问题:poll_ready 动了没有(就绪主线),call 返回的 future 换成了什么类型(请求主线)。答案几乎都是「poll_ready 原样转发,future 换一个不装箱的类型」,例外正是值得看的地方。
- service_fn 与 map 一族:
service_fn永远就绪;map_request、map_response、map_err、map_result、then、and_then、map_future各改哪一段,poll_ready的错误由谁转换;它们的 future 类型都不装箱,有的直接沿用内层的类型,有的是包着futures_util类型的 newtype。 - 类型擦除:分支返回不同的中间件栈时,编译器报什么错,
BoxService怎么修;BoxService靠SyncWrapper得到Sync;UnsyncBoxService、BoxCloneService、BoxCloneSyncService对内层的要求和自身的Send/Sync/Clone;代价是每个请求一次堆分配;BoxLayer一族。 - Either 与 FutureService:
Either不装箱地二选一,要求两边响应和错误类型相同;FutureService先在poll_ready里把「造服务的 future」驱动完,再把就绪查询交给造出来的服务。
flowchart TB fnode["闭包"] -->|service_fn| svc[一个服务] svc -->|"map_* / then / and_then"| shaped[改了形状的服务] shaped -->|"boxed / boxed_clone"| boxed["BoxService:类型擦除"] shaped -->|"Either::Left / Right"| either[两种服务之一] fut["造服务的 future"] -->|FutureService| svc
ServiceExt 里和调用有关的 ready、oneshot、call_all 不在这里,见 ServiceExt 与 Oneshot;option_layer 怎么用 Either 见 ServiceBuilder。
💬 关联讨论
发起讨论加载中...