Skip to content
All writing Part 07 of 11 · 從 19 個 goroutine 到 exit 137
Engineering · 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 排程器與 netpollerGOMAXPROCS 限制平行不限並發)。
  • 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)。

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

參考來源:

Related: 參見用 TryAcquire 做 load sheddingkeep-alive 讓重試卡在同一台錯誤的修法,或回到系列總覽

Tags #go #concurrency #reliability
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Youtube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration