你的零宕机部署大概没问题——先查 p99 再相信它
来源:dev.to — 2026-09-06
📋 概述
作者在滚动重启时寻找丢掉的请求,却找到了比丢请求更烦人的东西:一个看起来完美、其实并不完美的部署。两个 Node/Express 副本在 nginx 后面,十个客户端猛打一个耗时三秒的端点,中途 docker stop 一个副本,应用完全没有信号处理。他预期一堆积 502,结果是零失败——三次全零。请求确实死了,只是 nginx 在响应头发出前捕获了上游连接断开,静默连到另一个副本重跑了整个请求,客户端毫不知情。这个行为叫 proxy_next_upstream,默认开启,也正是仪表盘报告「完美部署」而部署的东西悄悄坏掉的原因。
🔑 核心要点
- 错误率会藏起问题:nginx 的 proxy_next_upstream 在响应头发出前抓到上游断开就静默重试到另一副本,客户端毫无察觉——同一零错误结果下,受影响请求被跑了两次
- 唯一露出破绽的是延迟:naive 应用 p99=5.94s(请求被执行两次),优雅关闭的 p99=3.04s——如果你只看错误率一无所有,看 p99 会在每次部署看到那根你大概已学会忽略的尖峰
- 重跑代价因工作而异:重试搜索查询零成本、重试外发邮件是封重复件、重试支付授权换来财务的一通电话——nginx 不知道它刚才重跑了哪一类
- 取走安全网才现原形:Kubernetes Service/L4 LB/直连 app 都不会重跑,关掉 proxy_next_upstream 后 naive 应用 70 请求失败 5 个(7%);应用层优雅关闭把失败降到 1/71,但最后那一个由「server.close() 到 LB 发现实例已离开」之间的窗口产生
- 正解是先把实例移出轮换再发 SIGTERM:preStop sleep 不是给应用(它早完成了),而是给端点移除传播留时间——三个排序正确后 0/70 失败,全部跑在笔记本上、无需云账号
💡 金句
Error rate is exactly the metric that will hide it if there's a retrying proxy in front of your app.
👍 0
👎 0
← 返回 dev.to 首页