Skip to content
All writing Part 04 of 11 · 從 19 個 goroutine 到 exit 137
Engineering · 1 min read

GOMAXPROCS 限制平行,不限並發

cpu:1 不代表一次只跑一個。I/O-parked 的 goroutine 不受 GOMAXPROCS 約束。平行和並發是兩個不同的上限。

cpu:1 不代表一次只跑一個。I/O-parked 的 goroutine 不受 GOMAXPROCS 約束。

三個層次的「看起來有限但沒有」

GOMAXPROCS = 1 Running (P-bound) G₁ Parked (netpoller) G₂ G₃ ... G₁₉ ← 1 max ← no limit parallelism = 1 (caps Go code) concurrency = 19 (caps nothing)
  1. net/http 的隱含並發:每個請求自動開一個 goroutine,handler 裡再 go 出去,N 個請求 ≈ 2N 個 goroutine,沒有框架級上限。
  2. GOMAXPROCS 只限平行:它限制同時「執行 Go 程式碼」的 goroutine 數量。I/O-parked 的不算。Parked goroutine 佔 0 P/0 M(GMP 排程器)。
  3. runtime.NumCPU() 的陷阱:讀的是 node 的 core 數(如 64),不是你的 cgroup quota(如 1)。pre-Go 1.25 需要 go.uber.org/automaxprocs 修正。但它只修 CPU,不修 memory OOM。

在這個 OOM 裡的角色

截圖服務用了 automaxprocsGOMAXPROCS=1。看起來像「一次只跑一個」,實際上 19 個 /capture goroutine 同時 parked 在瀏覽器 websocket 上,每個開了一個分頁。GOMAXPROCS 給了一種不存在的安全感。

真正的上限要自己加:semaphore(TryAcquire load shedding)。

GOMAXPROCS 是 CPU 的上限,不是資源的上限。I/O-bound 的工作需要你自己加限制。

參考來源:

Related: 參見GMP 排程器與 netpoller用 TryAcquire 做 load shedding,或回到系列總覽

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