恰好 1.00 秒的 P100

英文版:English

症状

某租户的检测 API 的 P100 钉在恰好 1.00 秒,每 5–10 分钟尖一次。P50 到 P95 保持健康的 1–2 毫秒。共享同一 ingress 层的几个租户在相同窗口受影响。没有任何东西宕机;某个东西在周期性地从最慢的请求身上偷走恰好一秒。

调查

三条线并行:访问日志与错误日志交叉比对、ingress 层配置全量审计(全局配置 → 渲染后的服务配置 → 每路由注解)、pod 级指标。

第一个转折:慢请求的 upstream_response_time 完全正常(20–30 毫秒)。这同时排除了上游服务和客户端:等待发生在代理层内部

第二个转折杀死了直觉假设。配置审计在整个渲染配置里只找到一处「1s」,而它是限流器的滑动窗口参数,不是代理超时。最显然的嫌疑人不存在。

决定性证据来自错误日志:限流插件的内联缓存查询(对着一个单副本 memcached)在超时,且每次超时都与慢请求的时间戳和客户端 IP 对齐。插件的客户端库默认读超时 1,000 毫秒。撞上缓存卡顿的请求等完整个超时再继续。恰好一秒,由定义决定。佐证信号:缓存只有一个副本、10 个工作线程,超时开始时它的文件描述符数从 24 跳到 54。

修复与回路学到的

交付的修复方案:缓存扩出单副本状态、提高线程池,以及最重要的一条,把插件读超时从 1,000 毫秒砍到 100–200 毫秒,让最坏情况退化成快速有界的 miss 而不是一秒的卡顿。为这个监控盲区上了 exporter。

整数尾延迟是人为常量,不是物理规律。当 P100 落在整数上,先查配置再看图。

这条启发式现在是我 triage playbook 里的常设规则,那个在插件里躲了多年的缓存层上了 dashboard。