Files
PolyGateway/research-wiki/findings/2026-07-21-p6-soak-baseline.md
T

5.5 KiB
Raw Blame History

P6 混合浸泡首跑基线与记分板三重伪击穿修复

  • 日期: 2026-07-21;run_id: soak_20260721_050750
  • 结论: 8000 次调用全部完成,库自身零缺陷;记分板两项 FAIL 均为测量口径缺陷(三重伪击穿),修复后离线重裁全部 PASS。修复分支 fix/soak-scoreboard-clock

1. 运行参数与规模

场景 P6 混合(P1 .10 / P2 .20 / P3 .35 / P4 .15 / P5 .20),SOAK 五源故障池
预算/实际 8000 次(签字帽)/ 8000 次全部完成;token 1401 万(硬顶 2 亿)
拓扑 2 worker × 32 并发 = 64 在途;限流/熔断/缓存全 Redis(db3);Postgres 遥测
用时 05:0706:54,约 1h47m(3h 上限内)
成本 23.42 元(价格表首次生效: 输入 2.1/输出 8.4 元/M tok;缓存命中 token=0 天然零成本)

2. 结果基线(P6 首跑,后续回归对照)

指标 说明
总成功率 4648/8000 = 58.1% 五源池 3 坏 1 紧闸;窗口成功率从开局 40% 爬至尾段 73%(熔断学习 + 缓存变热)
缓存命中 2373 次 P4 复读流量生效,命中秒回零成本
延迟(成功行) 总时长 p50/p95 = 6.8s/48.1s;TTFT p50/p95 = 22.0s/53.2s p50 远低于 P3 纯健康池(16.9s)系缓存命中行拉低;非缓存行与 P3 同量级
P3 结构化成功率(P6 内嵌) 0.218 故障池 + 网关 429 高压下的口径,不可与纯健康池基线 0.942 直接对比
RSS 实时 ps 采样: 10min 119MB → 40min 起稳定 36MB 至结束 无泄漏;峰值系 harness 自身无界入队(见 §4)

错误分布大头(共 20146 遥测行): 网关侧 429 限速 4845(minimax_5 3773 + minimax_1 996 + minimax_4 76)、紧看门狗掐流 3622(inter_token 3390 + ttft 232)、真实空补全 2211、retry_exhausted 终态 3318、黑洞超时 230、坏 key 31。

治理行为实证: 黑洞源走完 攒失败→开路→仅探针漏过 全周期(全程 230 次超时,开路后每 5 分钟仅 1 次探针);坏 key 源 force_open 后基本从遥测消失;跑后记账归零、探针不悬挂、call_id 唯一全 PASS。

3. 三重伪击穿: RPM "FAIL" 根因链

记分板判 minimax_4(RPM=5)单分钟 6-10 次。逐层排查(每层修完仍 FAIL 才发现下一层):

# 口径缺陷 证据 修复
1 完成时刻(created_at=落库时刻)聚桶,调用延迟达分钟级,多个准入窗口的调用挤进同一完成分钟 准入时刻 = created_at latency 重算后分布改变 按准入时刻聚桶
2 本机钟聚桶,而限流器窗口 id 来自 Redis 服务器钟(limiter.py:_window_id,CHS 移植的多进程口径统一设计) 实测 Redis 钟偏移 +30.98s;密集分钟 10 次准入在第 ~29 秒恰可切 5+5 记分时实测偏移并校正;秒级截断噪声给 ±2s 贴边豁免(邻窗有余量才可豁免)
3 缓存命中行计入 RPM——缓存在限流闸之前返回,未耗名额未打网关,但"遥测必录"使其带原源名落库 minimax_4 共 579 行中 347 行 cache_hit=1(洋葱序 Telemetry→Cache→…→Retry 内限流,命中行 latency=0 从未过闸) RPM 口径排除 cache_hit 行

修复后离线重裁(--rescore,不产流量): RPM PASS。精确说明(独立 verifier 复核): 剔除缓存行后仍有 2 个窗口 6 行,各含 1 行距右边界 0.2-0.7s——落在 created_at 秒级截断噪声的合理方向(截断只低估准入时刻,行只可能实属右邻窗),由分侧贴边豁免判为非击穿;并非"剔除后全部 ≤5"。verifier 另证明偏移敏感性: 就本数据集,offset=0 与 +31s 裁决相同(口径同源化仍是原则正确)。豁免逻辑经 verifier 对抗样例加固: 分侧(左贴边只可借左邻余量)+ 邻窗余量全局一次性消耗,防漏报真实击穿。

4. RSS "FAIL" 根因: 峰值口径 + 无界入队

  • _rss_mbru_maxrss——历史峰值只增不减;判"增长 782MB"实为开局峰值。
  • 峰值来源是 harness 自身: 分发循环 15 秒内把 4000 任务/worker(含 P2 ~313KB 图负载)全量 create_task,信号量只限执行不限入队;顺带使 --max-hours 截止检查随分发结束而失效、执行期无进度打印。
  • 库无泄漏: 运行期实时 ps 采样 36MB 稳定 90 分钟(本 finding §2)。

修复: ① _rss_mbps -o rss= 当前值;② 分发改 _paced_dispatch 有界模式(先占并发名额再建任务),截止检查全程有效、内存峰值受限、进度行全程可见;③ 旧格式结果(仅峰值序列)重裁时判 SKIP 不判 FAIL。

5. 交付物

  • tools/soak/scoreboard.py: inv_rpm_never_exceeded 新口径(准入时刻 + 服务器钟偏移 + 贴边豁免 + 排除缓存行)。
  • tools/soak/run_soak.py: _rss_mb 当前值、_paced_dispatch 有界分发、_redis_clock_offset_s--rescore RUN_ID 离线重裁模式。
  • 测试: tests/unit/test_soak_corpus.py 新增 9 用例(先红后绿,含 2 个 verifier 对抗样例),全套 CI 绿覆盖 90%。
  • 重裁报告: tests/outputs/soak/soak_20260721_050750.md(全 PASS/SKIP)。

6. 经验沉淀

  1. 不变量的口径必须与执法者同源: 限流器用什么时钟、在哪个时刻、对哪些流量执法,记分板就必须用同样的三元组重算;任何一元错位都产生伪击穿。
  2. 分布式系统验收前先测时钟偏移(本实验室 Redis 快 ~31s)。
  3. ru_maxrss 不可用于"平稳性"断言;峰值与当前值是两个量。
  4. "遥测必录"(含缓存命中)与"限流口径"(仅真实过闸流量)是两个集合,消费遥测时必须显式选择。