Skip to content
所有文章 ‹ Part 07 of 11 · 從 19 個 goroutine 到 exit 137
工程 · 3 min read

共享資源的影響範圍:當一個死,全部一起死

集中化省了資源,也集中了風險。一個共用瀏覽器死了,所有 in-flight 的請求跟著死。Bulkhead 被拆掉了。

集中化省了資源,也集中了風險。加回的限制就是 semaphore。

影響範圍反過來

BEFORE per-request (獨立瀏覽器) req1 req2 req3 Browser₁ Browser₂ Browser₃ AFTER shared (共用瀏覽器) req1 req2 req3 1 Browser blast radius: 1 request blast radius: ALL in-flight dies → req1 only ✓ ✓ → OOM exit 137 ALL fail

Backpressure 不會自動跨 process

Go runtime G1 G2 ... G19 scheduler 看得到 backpressure ✗ Browser 2Gi ceiling Go 看不見 Process boundary HTTP ✗ fix: semaphore + 429 在這裡(邊界上)
  • In-process 排程器只看得見自己 process 裡的資源。Out-of-process 的瓶頸 = 不可見,沒有自動 backpressure(GMP 排程器與 netpoller、GOMAXPROCS 限制平行不限並發)。
  • Bulkhead pattern = 刻意分區,一區壞了,其餘不受影響。共用 pool 是 anti-bulkhead(拆掉了隔離,一個出事全部受影響)。
  • 原則:集中化的時候,把隔離原本免費給你的上限補回去。

Fan-in 的數學

per-pod cap = 6 Pod₁ (cap 6) Pod₂ (cap 6) Pod₃ (cap 6) shared proxy (1 replica) max load = 6 × 3 = 18

Per-pod 的 cap 只約束本地 sidecar。如果下游是共享 singleton,N 個 replica 的 cap 加總就是實際負載。用 global limiter(Redis / Envoy)、per-replica resource(sidecar)、或 pull-based queue 才能真正 bound。

在這個 OOM 裡的角色

從獨立瀏覽器改成共用瀏覽器,省了啟動成本,但影響範圍從「一個請求」變成「所有 in-flight 請求」。Go runtime 不知道瀏覽器快滿了,沒有 backpressure,goroutine 繼續開分頁。修法:在 Go 端(process 邊界)加 semaphore + 429(用 TryAcquire 做 load shedding)。

一個共享資源沒有上限,等於整個系統沒有上限。

參考來源:

延伸閱讀: 參見用 TryAcquire 做 load shedding、keep-alive 讓重試卡在同一台、錯誤的修法,或回到系列總覽。

↑↓ 移動 ↵ 開啟 esc 關閉