常见坑
每一章对着一个报错或者一个现象:先用一个最小的程序把它复现出来,再到源码里找它是在哪一行产生的,最后给出修法,修法也跑一遍。机制本身在前面的章节讲过的,这里只链过去,不再重复。
- connection closed before message completed:
IncompleteMessage。最常见的是客户端从池里拿到一条服务端刚关掉的空闲连接;对端在响应头中途关闭、请求被送进一个直接断开的代理,报的也是它。body 读到一半断开报的是另一个错误。 - dispatch task is gone:连接任务所在的运行时没了。典型场景是多个
#[tokio::test]共用一个static的Client:串行全过,并行约一半的运行失败。只换执行器不够,socket 也要在长寿的运行时上建。 - You must supply a timer. 与 timeout
header_read_timeoutset, but no timer set:开了 HTTP/2 keep-alive 或显式设了读头超时,却没给 timer。auto::Builder的两半各有各的 timer;panic 只杀掉一条连接,服务看起来还活着。 - header_read_timeout 不生效,半个前言挂住连接:
axum::serve和auto::Builder::new都不设 timer,读头超时和 keep-alive 空闲上限都不存在;设了 timer,ReadVersion这一步仍然没有超时。 - invalid HTTP version parsed 与 found HTTP2 preface:HTTP/2 客户端打到只会 HTTP/1 的服务端,或 HTTP/1 客户端打到 HTTP/2 服务端、TLS 端口。TLS 握手打到明文端口报的却是方法名错误。
- message head is too large:请求头超过
max_buf_size或max_header_size,服务端回 431。 - 连接没有被复用:响应 body 没读完、空闲超时、
max_idle_per_host,连接回不到池里。 - 优雅停机一直不结束:长连接不会自己结束,
shutdown()要配超时。 - 一个慢请求卡住同一连接上后面的请求:HTTP/1 一条连接上的请求串行处理;HTTP/2 每个流一个任务。
- SOCKS error: failed to create underlying connection:直接用
SocksV5时,默认HttpConnector的enforce_http拒绝socks5://,或代理 URI 没写端口被按 80 连;原因只在{:?}里。 - tunnel error: unsuccessful:代理对 CONNECT 回了 200、407 以外的状态码,状态码不进错误;用 hyper 自己的客户端发 CONNECT 才拿得到。
flowchart TB cli["客户端主线"] --> p1["1 连接提前关闭"] cli --> p2["2 dispatch task 没了"] cli --> p7["7 连接不复用"] cfg["建连接时的配置"] --> p3["3 缺 timer"] srv["服务端主线"] --> p4["4 慢连接挂住"] srv --> p5["5 版本号解析失败"] srv --> p6["6 请求头太大"] srv --> p8["8 停机不结束"] srv --> p9["9 慢请求堵住连接"] prx["经代理建连接"] --> p10["10 SOCKS 连不上代理"] prx --> p11["11 CONNECT 被拒"] p3 --> p4 p1 --> p5
图里两条额外的线:3 和 4 是同一个开关(timer)的两面,给了不该给的选项会 panic,没给 timer 又会让默认超时悄悄失效;1 和 5 常常一起出现在「协议或端口弄错了」的场合,对端回什么字节决定你看到哪一个。读之前最好先读过 Dispatcher、conn::http1 客户端 和 Executor 与 Timer。
💬 关联讨论
发起讨论加载中...