常见坑
每一章对着一个报错或一个现象:先用最小的程序复现,再到源码里找它从哪一行来,最后给出修法和检查办法。前面几部分讲过的机制,这里只链过去。
复现环境都是 M2 Max、macOS 27、rustc 1.99.0、pingora 0.9.0、tokio 1.53.2(为什么钉这个版本见第 1 章)。和本站网关有关的几章,同时在网关用的 pingora 0.8.0 上复现,章里写明。有几个坑是上游的问题,章里写明 main 上修了没有。
- capacity must be greater than zero:tokio 1.54 起,第一个连接进来就 panic,监听停掉,进程还活着。
- the name
tlsis defined multiple times:两个 TLS feature 同时打开。 - No tls feature was specified:没选 TLS 后端也能编过,握手时才 panic。
- 升级到 0.9.0 的编译错误:
DerefMut没了(E0596 / E0594);CacheKey少了一个参数,照 rustc 的提示改会让键冲突。 - Worker threads cannot be set to 0:配置校验放过了
threads: 0。 - still in use:端口被占,重试约 30 秒后服务线程 panic,进程不退出。
-c配置文件不生效:Server::new(None)不读命令行。- grace period 300s starts:默认宽限期比容器的停机时限长,每次停机都被 SIGKILL。
- Upgrade is not currently supported outside of Linux platforms:macOS 上平滑升级失败,旧进程却说 listener sockets sent。
- 在钩子里阻塞:Steal 下所有新连接一起卡住(4 个线程 18/18 次);NoSteal 下 accept 线程一忙,整个服务都慢。
- 第一个请求之后,连接永不空闲超时:HTTP/1 keep-alive 的超时变成无限,h2 连接不发 preface 也一样。
- 管线化的第二个请求没有回应:默认关闭 pipelining,回完第一个就断开;第二个在代理途中到达时,连第一个也变成 400。
Some(H2Options::new())丢了默认上限:自己传 h2 选项,有界的默认值就没了。- Failed to load provided certificates:rustls 后端到 build 时才读证书,panic 后这个服务的所有端口都拒绝连接,明文端口也一样。
- failed to lookup address information:
HttpPeer::new同步解析,失败就 panic;localhost先走::1。 - 上游 h2 不复用连接:
max_h2_streams默认 1;对只会 h1 的 TLS 上游要 h2,每次都新建连接。 - 上游不回应,连接永远挂着:
PeerOptions默认没有任何超时。 - Upstream ConnectionClosed ... retry: false:复用的连接被上游关掉,0.9.0 的 POST 回 502,0.8.0 把 POST 发两次。
Ok(true)却没写响应:客户端一直等到超时。- Empty reply from server:
max_retries: 0一次也不连上游,也没有日志。 - Retry is not decided:覆盖
error_while_proxy时没有决定ReusedOnly。 - 响应带 Vary 却没压缩:在
request_filter里才打开压缩,已经晚了。 - 打开了缓存却什么都没缓存:默认的
response_cache_filter一律不缓存。 - POST 命中 GET 的缓存、Set-Cookie 发给别人:缓存的默认判断不看方法、不看 Set-Cookie、不看 Vary。
- response too large:超过最大文件大小时,chunked 响应被截断,客户端可能一个字节都拿不到,日志却写 status 500。
- attempt to calculate the remainder with a divisor of zero:后端权重全是 0。
- assertion failed: new >= now - 1000:
Rate的窗口小于 1 秒、多线程同时用,上游问题。 RTCache的写者被取消后:同一个键永远等,或者永远 miss,上游问题。
按出在哪里分:
| 出在哪里 | 坑 |
|---|---|
| 依赖与 feature | 1 tokio 1.54、2 两个 TLS、3 没有 TLS、4 升级到 0.9.0 |
| 服务器与停机 | 5 threads 0、6 端口被占、7 配置不生效、8 宽限期、9 macOS 升级、10 阻塞 |
| 下游协议 | 11 keep-alive、12 管线化、13 h2 选项、14 rustls 证书 |
| 连接上游 | 15 DNS、16 h2 复用、17 没有超时、18 复用连接上的 POST |
| 代理钩子 | 19 Ok(true)、20 max_retries、21 ReusedOnly、22 压缩 |
| 缓存 | 23 不缓存、24 不安全的默认、25 最大文件大小 |
| 负载均衡与组件 | 26 权重 0、27 Rate、28 RTCache |
本站网关(pingora 0.8.0)中了其中几个:1 的风险(锁文件挡着)、8、11、18,见在本站中。
flowchart TB
q{"碰到了什么"}
q -->|编译失败| cf{"哪一句"}
cf -->|"E0252 tls"| p2["2 两个 TLS"]
cf -->|"E0596 E0594 E0061"| p4["4 升级 0.9.0"]
q -->|启动就 panic| st{"原文"}
st -->|"threads"| p5["5 threads 0"]
st -->|"still in use"| p6["6 端口被占"]
st -->|"Upgrade is not"| p9["9 macOS 升级"]
q -->|请求时 panic| pn{"原文"}
pn -->|"capacity"| p1["1 tokio 1.54"]
pn -->|"No tls feature"| p3["3 没有 TLS"]
pn -->|"certificates"| p14["14 rustls"]
pn -->|"lookup address"| p15["15 DNS"]
pn -->|"Retry is not"| p21["21 ReusedOnly"]
pn -->|"divisor of zero"| p26["26 权重 0"]
pn -->|"now - 1000"| p27["27 Rate"]
q -->|客户端拿到错误| ce{"哪种"}
ce -->|"POST 502"| p18["18 复用连接"]
ce -->|"Empty reply"| p20["20 max_retries"]
ce -->|"一直等"| p1917["19 或 17"]
ce -->|"body 截断"| p25["25 文件大小"]
q -->|行为不对| bh{"哪种"}
bh -->|"配置没生效"| p7["7 或 13"]
bh -->|"连接不关"| p11["11 keep-alive"]
bh -->|"停机被杀"| p8["8 宽限期"]
bh -->|"全部变慢"| p10["10 阻塞"]
bh -->|"缓存不对"| p2324["23 或 24"]
bh -->|"没压缩"| p22["22 压缩"]
bh -->|"连接太多"| p16["16 h2"]
bh -->|"键永远等"| p28["28 RTCache"]
💬 关联讨论
发起讨论加载中...