本地推理叢集怎麼租到「假健康」:停機演練裡踩的三個坑
上週把我們本地推理叢集接上生產環境的最後一週,CI 全綠、監控全綠、fallback 鏈路演練也「成功」了。結果第一次真正擋住上游流量的那天,復原動作的第一步就卡住了——我們按故障預案滾動重啟「不健康的節點」,排出來的一台其實是最健康的那台。

本地推理叢集怎麼租到「假健康」:停機演練裡踩的三個坑
上週把我們本地推理叢集接上生產環境的最後一週,CI 全綠、監控全綠、fallback 鏈路演練也「成功」了。結果第一次真正擋住上游流量的那天,復原動作的第一步就卡住了——我們按故障預案滾動重啟「不健康的節點」,排出來的一台其實是最健康的那台。
問題不在重啟腳本,而在於我們給「健康」這個詞定了兩套標準,兩套標準在平常時候都對,在故障時候互相打架。
坑一:兩種健康判斷,兩套真相
我們當時有兩層判斷:
- **探測層**:定時打 /health,回傳 200 就算活著。
- **負載層**:按佇列深度和排隊耗時標記節點「過載」。
停機演練時,路由器把過載節點從調度池裡摘除。第二天排查日誌發現摘除的那批節點,探測層視角全是綠的,負載層視角全是紅的。兩邊都沒錯,但復原手冊寫的是「重啟探測失敗的節點」,按這個步驟操作,重啟的就是負載最高、但還活著的那台。
後來把約定寫死在應急預案裡:**調度摘除用負載層指標,重啟作用於進程級探測,兩者不共用「不健康」這個標籤**。現在復原手冊第一頁就貼這個對照表。看起來是文件活,其實是將兩套判定層解耦的活,省一次凌晨四點的誤重啟。
坑二:fallback 演練「成功」,是因為演練裡根本沒有真流量
我們的路由器配置是:主路由 127.0.0.1:4000,fallback 走雲端。演練方式是把主路由進程 kill 掉,再發幾個測試請求——全走了 fallback,演練通過。
但生產環境第一次真故障時我們發現,超時的那批請求根本到不了 fallback 決策點:它們在用戶端到主路由的連線層就卡死了,TCP 建連成功、write 成功、read 超時,用戶端的 retry 邏輯直接原地重試三次。fallback 只在「請求成功到達路由器且被拒絕」時才生效。
補的修法:用戶端超時從 30 秒砍到 8 秒,加一個連線池的空閒超時;路由器側增加「佇列超過閾值主動回傳 503」,讓請求在到達 fallback 決策點之前就先失敗,而不是懸掛在佇列裡。這次演練的教訓不是 router 配錯了,而是**演練流量和生產流量的失敗點不在同一層**,只對演練覆蓋的那一層做了驗證。
坑三:同一個 IP 同時當路由器和資產來源
另一個細節:本地路由器進程同時託管了靜態封面圖的 HTTP 端點。路由器重載設定的時候,去拉新文章封面的任務同時被中斷,文章發布流程報「封面 404」,排查了快四十分鐘才發現是同一個進程佔用同一個連接埠。
拆法很簡單:靜態檔案挪到獨立連接埠,路由器的 image 端點只管 image。一小時的故障時間換了一條規矩:**一個連接埠只承擔一種故障域**,任何「順便」掛上去的東西都要單獨列故障預案。
收尾
這三件事單看都不複雜,共同點是:健康判定、失敗路徑、故障域,三樣東西在「系統活著」的時候互相掩蓋,系統出問題時才會顯形。演練的價值不是給綠勾,是把這三套標準各自寫清楚、並且確認它們描述的是同一次故障。
現在每次停機演練,檢查單第一項不是「服務恢復了」,是「我們用的健康標籤是不是同一套」。
留言區
歡迎分享你的想法!
載入留言中…