目的

复盘 2026-08-02 10:00 左右站管家“报价不行”的故障。重点回答两个问题:

  1. 最早的故障到底出现在 VinAudit、basedata 还是 sale。
  2. 为什么重启数据平台无效,而重启 basedata 后还必须再重启 sale 才恢复。

最终结论

  • 已证实的根因主链:basedata 内部出现约 31 秒的同步阻塞,先触发 sale -> basedata JSON-RPC 接收超时与响应 ID 错配,随后扩散到 VinAudit 和报价页面。
  • 已证实的恢复机制:重启 basedata 只能修复服务端卡住和串包;sale 进程中的长连接池仍保留坏连接,因此会继续报 Client no connection,必须再重启 sale 才能清空积压和失效连接。
  • 仍未完全证实的底层触发:basedata 的静默窗口高度怀疑落在同步 Mongo 聚合或到 Mongo 的选服/连接阶段,但实例慢日志已滚动覆盖,当前没有平台侧最终证据把它写成“某个 Mongo 节点故障”。

时间线

时间已验证证据结论
09:55:36basedata 内部出现 20~35s 阻塞窗口故障起点早于 VinAudit 硬超时
09:55:43sale 首次报 basedata JSON-RPC errno=110 Operation timed out调用端先感知到 basedata 卡住
09:55~10:00sale 出现大量响应 ID 错配RPC 长连接已被迟到响应污染
10:03:43站管家对 VinAudit /product/detail 出现首个 5 秒硬超时VinAudit 是被放大的后续症状,不是首发点
10:09重启 basedata 后,ID 错配 消失,但 sale 仍大量报 Client no connection服务端恢复,但调用端坏连接未清空
10:14重启 sale 后错误量快速归零清空积压协程与失效 RPC 连接后恢复

证据链

1. 为什么不是先从 VinAudit 开始

  • VinAudit 的硬超时出现于 10:03:43,晚于 sale -> basedata 的首次超时约 8 分钟。
  • 在 VinAudit 首次硬超时前,sale 已经出现大批 JSON-RPC 超时和响应 ID 错配。
  • 这意味着“报价页面超时”不是先由 VinAudit 单点引发,再反向拖垮 sale/basedata;相反,是上游调用链先异常,后续才把 VinAudit、负载图和报价页面一起放大成可见故障。

2. 为什么重启 basedata 还不够

  • basedata 重启后,sale 不再主要报 errno=110 Operation timed out,而是转成大量 errno=5001 Client no connection。
  • 新错误大多在 1~3s 内立即失败,不是继续等待 10s 或 20s 超时,说明问题已从“服务端不回包”变成“调用端继续复用已经失效的连接”。
  • 因此必须再重启 sale,才能把旧协程、长连接池和积压请求一起清空。

3. 为什么把底层卡顿收敛到 basedata 同步阻塞

  • 多个样本都显示 MySQL 查询本身只需毫秒级完成,但库存 HTTP 调用要在 27~35s 后才返回或才开始。
  • 在一部分样本中,MySQL 已完成,库存 HTTP 尚未开始,中间存在约 31s 的静默窗口。
  • 这段窗口既不属于“某条 SQL 慢”,也不符合“单纯库存中心慢”的形态,更像 basedata worker 在同步阶段被阻塞,随后同一批等待请求被集中唤醒。

仍未证实的部分

  • Mongo 副本集当前 uptime 与 electionTime 排除了“昨天 09:55 左右发生重启/选主”的猜测。
  • 但 Mongo profiler 的最早记录已滚动到当天凌晨,无法直接回看 09:55 的慢操作。
  • 因此不能把“某个 Mongo 节点网络抖动”或“Mongo 实例故障”写成已证实事实;当前只能写成“阻塞高度怀疑位于同步 Mongo 阶段或其连接/选服过程”。

复用排查顺序

  1. 先按分钟对齐 sale、basedata、VinAudit 三侧最早错误时间,判断是首发点还是后续症状。
  2. 看 sale 的错误类型是否经历 errno=110 -> ID 错配 -> Client no connection 三段变化。
  3. 在 basedata 单请求链路里切开 MySQL 完成时间、库存 HTTP 开始时间 和 RPC 响应吐出时间,找静默窗口。
  4. 区分“服务端卡住”和“调用端坏连接未清空”:前者表现为超时等待,后者表现为快速 Client no connection。

验证与代码入口

  • DGJ2 工作区:/Users/zhoujiangbin/code/docker-dev-env/www/dgj2.0
  • VinAudit 工作区:/Users/zhoujiangbin/code/docker-dev-env/www/VinAudit
  • sale 工作区:/Users/zhoujiangbin/code/docker-dev-env/www/dgj-sale-service
  • basedata 工作区:/Users/zhoujiangbin/code/docker-dev-env/www/dgj-basedata-service
  • 故障日原始归档:/Users/zhoujiangbin/.codex/daily-reviews/source/2026/08/2026-08-03.json
  • 当日公开日报:/Users/zhoujiangbin/code/docker-dev-env/www/tengxunyun/work/team-manage-local/interview_docs/16_工作总结与述职/2026/日报/2026-08-03_工作总结.md

建议的只读核对命令:

rg -n "Operation timed out|Client no connection|response id" /Users/zhoujiangbin/code/docker-dev-env/www/dgj-sale-service
rg -n "getSaleMaterielPageList|inventory/allow/detail|aggregate" /Users/zhoujiangbin/code/docker-dev-env/www/dgj-basedata-service /Users/zhoujiangbin/code/docker-dev-env/www/dgj2.0
rg -n "product/search|product/detail" /Users/zhoujiangbin/code/docker-dev-env/www/VinAudit

下一步不要忘的事

  • 把 sale RPC 池的失效连接淘汰策略、basedata 的 Mongo 同步调用方式和超时层级分开治理,不要继续用一次重启同时掩盖三类问题。
  • 如果未来再次出现类似故障,优先保留 Mongo 实例侧 09:55~10:05 的慢日志/监控截图,否则平台证据会再次滚动丢失。