Disgn

在軟體系統中,「斷路器」是一種保護機制,用來避免系統在發生連續錯誤時被拖垮。它的核心目標是當外部服務或資源連續失敗時,暫時中斷請求,讓系統有時間恢復

家裡的電路,如果有電器短路,會造成電流暴增。斷路器就會「跳電」,暫時切斷電力,避免整個家被燒掉。在軟體中也是一樣,如果外部 API 一直回錯誤(例如 Timeout 或 500 Error),我們不應該一再重試,否則會耗盡 Thread、CPU、甚至把整個應用拖慢。所以斷路器會「跳閘」,暫停對那個外部服務的呼叫一段時間

狀態 意義 行為
Closed(關閉) 一切正常 請求會照常發送。如果有失敗,會記錄下來。
Open(開啟) 外部服務被認定「壞掉」 直接阻擋呼叫,立即回錯誤,不再嘗試。
Half-Open(半開啟) 試探階段 過一段時間後,允許少量請求試試看服務是否恢復。成功就恢復 Closed。

Polly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using Polly;
using Polly.CircuitBreaker;
using System.Net.Http;

var httpClient = new HttpClient();

// 定義斷路器策略
var circuitBreakerPolicy = Policy
.Handle<HttpRequestException>() // 要攔截的例外
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: 3, // 允許連續 3 次失敗
durationOfBreak: TimeSpan.FromSeconds(10) // 之後暫停 10 秒
);

for (int i = 0; i < 10; i++)
{
try
{
await circuitBreakerPolicy.ExecuteAsync(async () =>
{
Console.WriteLine("呼叫外部 API 中...");
var response = await httpClient.GetAsync("https://example.com/api");
response.EnsureSuccessStatusCode();
});
}
catch (BrokenCircuitException)
{
Console.WriteLine("⚡ Circuit is OPEN — 呼叫被阻擋!");
}
catch (Exception ex)
{
Console.WriteLine($"❌ 呼叫失敗: {ex.Message}");
}
}
  • Handle<HttpRequestException>() - 告訴 Polly:只要發生這類錯誤,就記錄一次「失敗」。

  • CircuitBreakerAsync(3, TimeSpan.FromSeconds(10)) - 如果連續錯誤達 3 次,進入 Open 狀態,
    接下來 10 秒內所有呼叫都會被拒絕。

  • BrokenCircuitException - 表示斷路器已打開(跳閘),呼叫被攔截。過了 10 秒後,自動進入 Half-Open,允許幾次試探性呼叫。如果成功 → 回到 Closed;失敗 → 繼續 Open

怎麼設計

  • 設定閾值(多少次錯誤才跳閘)
  • 設定冷卻時間(多久再試)
  • 處理不同錯誤型態(例如 Timeout、500、DNS 問題等)

啟動依據

  • CPU / 記憶體使用率(Resource Usage-Based)

  • 請求失敗率(Error Rate-Based)

  • 延遲時間過長(Latency-Based)

  • 關鍵功能(如:結帳流程、購物車):以延遲時間與錯誤率為主,迅速啟動斷路器,以免使用者「卡在」付款頁

  • 次要功能(如:商品推薦、即時聊天、評價讀取):以資源用量為主,在資源吃緊時主動關閉,保護核心流程順暢

另外也可以設計一個漸進式降級策略:例如先關閉圖片載入,再關閉推薦,最後才進入維護模式

次要、切換順序?

如果斷路器(Circuit Breaker)被錯誤地套用在太多功能上,可能導致使用者體驗下降。例如,推薦商品或庫存查詢被暫時中斷,是否仍會影響轉換率?這需要明確的優先級策略

斷路器觸發後,使用者看到的是什麼?

雖然技術上避免了系統崩潰,但如果介面只顯示錯誤或空白,使用者仍會覺得系統不穩。設計上需思考「優雅降級」或「替代內容」的體驗策略

斷路器的閾值如何設定?是靜態還是動態?

若閾值設定過低,容易誤觸造成服務中斷;過高則失去保護效果。這反映了技術設計與實際流量行為間的矛盾,需要動態監控與自我調整機制

類型 說明 優點 缺點
靜態閾值 事先寫死在設定中,例如「錯誤率超過 50% 就觸發」 簡單、可預測 不能自我調整,遇到流量暴增可能過於敏感或遲鈍
動態閾值 根據實際流量或系統負載自動調整,例如用滑動平均、AI 或監控資料計算 彈性高、適應性強 較複雜、需要監控與演算法支援

滑動時間窗口(Sliding Window)

系統不看全部歷史,而只看最近一段時間(例如最近 1 分鐘或 100 次請求)來動態估算失敗率或延遲。

failureRateThreshold: 動態 = (最近100次呼叫失敗率)
slowCallRateThreshold: 動態 = (最近10秒內慢呼叫比例)

🔹 優點:隨著流量波動自動調整,對電商高峰期特別有用。
🔹 缺點:需監控即時指標,運算略複雜。

基於「統計分佈」的閾值(Percentile-based)

不是看平均值,而是根據分佈百分位(如 p95、p99)設定閾值。
例如:只要反應時間超過「過去5分鐘第99百分位」就視為異常。

動態閾值 = 過去 5 分鐘 p95 延遲時間 × 1.5

🔹 優點:可精準反映真實延遲情況,不怕偶發尖峰。
🔹 缺點:需有穩定的監控資料來源。

在資源不足的情況下,是否有其他擴充方案?

使用斷路器只是「緩解」,非「根治」。根本的問題可能在於基礎架構(如自動擴容、快取機制、資料庫優化)。要反思是否依賴了權宜之計而忽略長期穩定性