MapleCheng

在浩瀚的網路世界中無限潛水欸少年郎!

0%

即時 AI Agent 的負載,不是一條連線而已

做即時 AI Agent 時,很容易把它想成另一種 Web 服務:前面放一層負載平衡器,後面開多個實例,再根據 CPU、記憶體或連線數分流。這套方法不是錯,但最近我越來越確定,它只看見了機器的忙碌,沒有看見 Agent 正在承擔的工作。

一條語音連線可能只是等待使用者開口,也可能正在做語音辨識、維持長上下文、呼叫工具,甚至同時委派背景任務。表面上都是一個 session,實際成本卻差很多。如果平台仍把它們當成相同單位,系統通常會在流量真正上來時,才暴露出延遲飄移、資源傾斜與「幽靈 session」這些難追的問題。

連線數是一個方便但危險的近似值

傳統 Web 請求多半短暫而相對獨立。請求進來、程式處理、回應送出,資源很快釋放。即時 Agent 則不同:WebSocket、串流音訊與長任務可能讓 session 存活數分鐘甚至更久,期間還會反覆在「等待」與「高負載」之間切換。

因此,只看連線數會產生兩種誤判。

第一種是把安靜的連線估得太重。某個節點可能掛著很多 session,但大部分使用者正在聽回覆或暫停說話,實際 CPU 並不高。若負載平衡器只按連線數判斷,它可能過早把新流量趕到其他節點,造成資源利用不平均。

第二種是把忙碌的連線估得太輕。另一個節點只有少數 session,卻都在進行音訊處理、模型推論、工具呼叫與上下文整理。連線數看起來很健康,延遲卻已經開始上升。等 CPU 指標反映出來時,使用者可能早就聽見卡頓。

我會把這件事理解成:連線數描述的是「有多少人還在場」,不是「系統現在做了多少工作」。兩者有關,但不能畫上等號。

Session 應該成為一級營運指標

即時 Agent 的調度需要認得 session 狀態,而不是只認得 socket 是否存在。至少要能區分:剛建立、等待輸入、接收音訊、生成回覆、執行工具、等待外部系統、背景處理、準備結束,以及清理中。

這不是為了把狀態機畫得漂亮,而是每個狀態的資源輪廓不同。等待輸入可能只占少量記憶體;生成語音需要推論與串流;工具呼叫可能不吃很多 CPU,卻會占住工作槽與外部 API 配額;背景任務則可能在使用者結束對話後仍繼續運作。

從平台角度看,我會希望每個節點至少回報三類資訊:目前活躍 session 數、各狀態的分布,以及近期每個 session 消耗的工作量。工作量不一定要一開始就做成精準計費,可以先用簡單權重估算,例如音訊處理、模型生成、工具等待與背景任務各自給不同分數,再和 CPU、記憶體、GPU 佇列及回應延遲一起判斷。

重點不是發明完美公式,而是承認「一個 session」不是固定大小的工作單位。

幽靈 session 不是小 bug,是容量治理失真

長連線系統另一個常見陷阱,是連線已斷,但 session 沒有被完整清掉。原因可能是網路瞬斷、客戶端直接關閉、逾時處理競態、背景任務卡住,或同一個清理流程被重複觸發後留下半套狀態。

這類幽靈 session 的麻煩,不只在於浪費一點記憶體。它會污染整套調度判斷:節點以為自己還很忙,負載平衡器不再分配新連線;容量報表高估同時在線人數;自動擴縮容被錯誤觸發;最後團隊甚至無法分辨成本上升來自真實使用,還是生命週期沒有收乾淨。

所以 session 清理必須具備冪等語意。同一個 session 不管因正常結束、逾時、網路錯誤或人工取消進入清理,重複執行都應得到相同結果:釋放資源、撤銷租約、停止或轉移背景工作、更新狀態,並留下可追蹤的終止原因。

我也會為 session 設計租約或 heartbeat。系統不能因為建立過一筆紀錄,就永遠相信它還活著;它需要定期證明自己仍然有效。逾期後則進入明確的回收流程,而不是直接從資料表消失,讓問題無跡可尋。

擴縮容要看壓力,也要尊重對話

即時服務的 scale out 相對直覺:壓力上升就增加節點。真正麻煩的是 scale in。一般無狀態服務可以停止接新請求,等短請求結束後關機;即時 Agent 節點可能仍握有長對話、音訊緩衝、上下文與尚未完成的工具呼叫。

如果縮容只看平均 CPU 下降,直接終止節點,使用者感受到的不是一次普通重試,而是整段對話失憶。因此節點需要有 draining 狀態:停止接收新 session,允許既有工作在時限內完成;無法完成的任務則要有明確的移交、checkpoint 或重新連線策略。

這裡沒有一種適合所有系統的答案。短客服對話可以接受重新連線,長時間協作可能需要 session state 外部化;涉及正式操作的工具任務,更要靠冪等鍵避免移交後重複執行。重要的是,縮容不能只是基礎設施事件,它也是使用者旅程與業務一致性的一部分。

我會怎麼開始做

如果團隊正準備把即時 Agent 推向正式環境,我不會一開始就打造複雜的智慧調度器,而會先完成四件事。

第一,定義 session 狀態與終止原因,讓生命週期可觀測。第二,把活躍 session 與 CPU、記憶體、推論佇列、延遲放在同一張營運視圖,而不是各看各的。第三,為逾時、斷線與重複清理寫行為測試,刻意製造不正常結束。第四,在縮容演練中確認 draining、背景任務與工具呼叫不會被粗暴截斷或重複執行。

這些工作看起來不像模型能力,卻會直接決定 Agent 是否真的能上線。Demo 階段,一條連線就是一個使用者;正式營運後,一條連線背後是一段會等待、推論、呼叫工具、失敗、恢復與結束的生命週期。

即時 AI Agent 的負載平衡,最終不是把連線平均分給機器,而是把不同階段的工作安全地分配、完成並收乾淨。當平台能回答「誰還活著、誰正在忙、誰其實已經離開,以及離開後是否真的清理完成」,容量與體驗才算進入可治理的狀態。