那次 P99 延遲翻倍,問題不在模型
上個月協助一個內部團隊進行意圖分類服務的性能除錯。區域監控顯示 P99 延遲從 310ms 悄悄漲到 740ms,持續了大約三天才有人發出警報。模型沒變、GPU 沒變、prompt 模板也沒動——第一反應是去找基礎設施團隊,查了一下午也沒找到異常點。最後真正的原因出在請求閘道層:一個上線時沒有任何監控覆蓋的限流中介軟體

那次 P99 延遲翻倍,問題不在模型
上個月協助一個內部團隊進行意圖分類服務的性能除錯。區域監控顯示 P99 延遲從 310ms 悄悄漲到 740ms,持續了大約三天才有人發出警報。模型沒變、GPU 沒變、prompt 模板也沒動——第一反應是去找基礎設施團隊,查了一下午也沒找到異常點。最後真正的原因出在請求閘道層:一個上線時沒有任何監控覆蓋的限流中介軟體,將聊天後台的批次預處理任務和線上請求塞進了同一個連線池。
這件事本身不大,但它暴露了 AI 交付專案裡三個反覆出現的坑,都值得單獨寫下來。
第一,核心鏈路漏掉了「中介軟體層」的指標
我們整套推論服務原來的監控只打在應用層:token 數、首包時間、請求本體大小。這套指標在平時很好用,但這次的問題發生在閘道,應用層的每一項看起來都正常。事後我們補了三組指標:閘道等待時長、連線池命中率、以及同一個租戶的請求排隊深度。
這裡有個取捨我覺得很多團隊會猶豫:中介軟體指標會很密,dashboard 會變得很吵。我後來的做法是,把中介軟體層的 P99 直接打到獨立的警報通道,不進主 dashboard,避免日常雜訊把真問題淹沒。
第二,批次任務走同一個執行緒池,等於沒有隔離
後台的批次生成任務用的是同一個 FastAPI 的 worker 行程。單看批次端點本身沒有 bug——它就是慢,但它會阻塞整個事件迴圈,線上請求的延遲就直接被拖上去。等我們把批次任務拆到獨立的 worker 行程之後,類似的情況就沒再出現過。
拆行程的成本很低,但前提是有人問出這個問題。這次的教訓是:性能 review checklist 裡應該加一欄,明確列出哪些端點共用資源、哪些是隔離的,而不是每次都事後回顧。
第三,警報閾值參考的是平均值,不是分位數
最初的 P99 警報閾值是 500ms,但真正觸發警報的是請求本體的超時,不是 P99 指標本身。也就是說監控系統確實看到了問題,但歸因指向了錯誤的層級,除錯往錯誤方向走了大半天。後來把閾值改成分位數疊加結構:絕對值 600ms 警報一次,連續兩個視窗超過基線 30% 再警報一次。比單一閾值敏感也不至於炸出太多誤報。
修復流程值得單獨固化
這次從發現問題到恢復,實際耗時 22 分鐘,流程是:切換閘道限流開關 → 批次 worker 走獨立執行緒池 → 觀察 P99 → 收口。整個過程裡沒有一個步驟是我臨場想的,全靠事先寫下來的 runbook。
我的習慣是把「恢復方案」和「定位方案」分開維護:恢復方案是 checklist,保證壓力下的動作不會跑偏;定位方案是除錯路徑的知識庫,事後用來積累。混在一起寫,通常兩邊都做不好。
這次的坑都不難,但每一個都需要「提前有人想到」才少踩一次。監控沒有及格線,只有夠不夠細;隔離也不是門禁,只是資源拆分的問題。如果這次的性能除錯對你有參考價值,那這些具體指標名和拆行程的判斷,就是我最想留下的乾貨。
留言區
歡迎分享你的想法!
載入留言中…