多區部署與故障轉移:模型服務的高可用設計
GPU 資源稀缺讓高可用比一般服務更難。這是務實的分級策略。
一般 Web 服務的高可用做法是多開幾台。模型服務不行——GPU 昂貴且供給有限,「多開幾台」的成本可能是原本的三倍。
務實的做法是分級:核心功能做真正的高可用,次要功能接受降級。
三層備援策略
- 同區多副本:最基本,處理單機故障。至少兩個副本。
- 跨區備援:處理整個區域故障。成本高,可用較小的機型或較小的模型。
- 外部 API 備援:自架全掛時,切換到商業 API。成本按用量計,平時不花錢。
第三層最被低估
把商業 API 當成最終備援,是模型服務特有的優勢——你不需要為備援常駐付費,只在災難時才產生費用。前提是介面要事先抽象好,切換不需要改程式。
PROVIDERS = [
{'name': 'self-hosted-a', 'weight': 100, 'health': True},
{'name': 'self-hosted-b', 'weight': 0, 'health': True}, # 熱備
{'name': 'commercial', 'weight': 0, 'health': True}, # 災備
]
def pick_provider():
healthy = [p for p in PROVIDERS if p['health'] and p['weight'] > 0]
if not healthy:
# 全部主要來源不可用 → 啟用災備
fallback = next(p for p in PROVIDERS if p['name'] == 'commercial')
alert('已切換至商業 API 災備,請立即處理')
return fallback
return weighted_choice(healthy)健康判定要基於真實請求
不要只靠健康檢查端點。用「近期真實請求的成功率與延遲」判斷,滑動視窗式地更新健康狀態,反應會快得多也準確得多。
class HealthTracker:
def __init__(self, window=50, fail_thr=0.3):
self.recent, self.window, self.fail_thr = deque(maxlen=window), window, fail_thr
def record(self, ok):
self.recent.append(ok)
def healthy(self):
if len(self.recent) < 10:
return True # 樣本不足時不判死
return (1 - sum(self.recent) / len(self.recent)) < self.fail_thr降級的層次
- 降模型:切換到較小的模型,品質降但仍可用。
- 降功能:關閉重排、縮小 k 值、取消自我修正迴圈。
- 降服務:只服務付費使用者或關鍵路徑。
- 明確停用:清楚告知使用者功能暫時無法使用,並給預估恢復時間。
演練是必要的
故障轉移的程式碼寫了不代表能用。至少每季演練一次:主動關掉一個副本,觀察切換是否順利、告警是否觸發、降級是否符合預期。
災備用的商業 API 金鑰與配額要定期驗證。真正需要時才發現金鑰過期或配額為零,是很常見的悲劇。
訂閱後繼續閱讀全文
本篇為訂閱者專屬內容。訂閱後可取得下列權限:
- 解鎖全部內容權限
- 閱讀不限篇數
- 全站移除廣告
月卡
NT$240
開通 30 天
一次付清,開通 30 天
季卡
NT$620
開通 90 天
一次付清,開通 90 天,每天約 NT$7
年卡
NT$2,160
開通 365 天
一次付清,開通 365 天,每天約 NT$6
一次性付款,付款成功後立即開通,到期自動結束,不會再次扣款,也不需要取消訂閱。
立即訂閱
金額均為新臺幣(TWD),即實際扣款金額,不另收手續費
支援信用卡 · Apple Pay · Google Pay · WebATM · ATM 轉帳
購買須知與退款政策