【從一台 Server 到分散式架構】第 03 篇:要升級機器,還是多加幾台?——垂直 vs 水平擴充
上一篇談到,小明他們的課程平台在負載上來之後,瓶頸在資料庫,首頁變慢、有時 504。除了從 DB 那層優化(索引、查詢、之後的讀寫分離與快取),後端這層也可能已經快撐不住,或他們想一併把容量拉高。
這時候就要做一個決定:是把現有機器升級(加 CPU、加記憶體),還是多加幾台後端,讓請求分散到多台機器?這就是垂直擴充與水平擴充的取捨。這一篇先講兩者的定義、什麼情境選哪一種,以及若選水平擴充,前面要擺誰來分流——實務上常用 Nginx 或雲端負載平衡器來做這件事。最後會預告:選水平之後,會遇到一個新問題(多台後端時,請求打到不同台,Session 或狀態會亂),下一篇再談。
什麼叫垂直擴充、什麼叫水平擴充?
垂直擴充(vertical scaling)就是:把同一台機器變強。例如原本 2 核 4G,升級成 8 核 16G;或換成更大、更快的磁碟。資源變多,同一份程式就能處理更多請求。優點是現有架構不用改變、程式碼也不用改,只要換機器或升規格就好;缺點是單機有上限,而且升級到一定程度後,成本會變貴、CP 值變低。
水平擴充(horizontal scaling)就是:多加幾台機器,讓多台一起扛流量。例如從一台後端變成兩台、三台,請求分散到各台,總體能處理的流量就上去。優點是理論上可以一直加機器、擴充彈性大;缺點是現有架構會有大幅度調整——前面要多一層負載平衡、多台機器要部署與維運,而且程式碼也可能需要調整,例如 Session 不能只存在單機記憶體、要改存共用儲存或改成無狀態,否則多台時會亂(下一篇會談)。所以選水平,除了成本與流量,也要把「架構與程式要動多少」算進去。
所以當小明他們發現單機已經快撐不住,或預期流量還會再上去,就要在「先升級這台」與「多加幾台」之間做選擇。
什麼情境選垂直、什麼情境選水平?
沒有絕對答案,要看成本、上限、維運、彈性,以及有沒有突發流量。先用小明他們的情境帶一次,然後整理成一套比較通用的判斷方式。
小明他們現在是:一台 2 核 4G 的後端,差不多 200 人同時在線就快撐不住。接下來有幾種常見的想法:
- 直接把這一台升級到 4 核 8G、8 核 16G(垂直擴充),希望同一台可以扛更多人。
- 保持 2 核 4G 這種小台,改成兩台、三台,前面加一層負載平衡(水平擴充)。
- 先垂直一兩階撐一陣子,以後流量真的起飛再改水平。
這些想法背後,其實都繞著幾個關鍵問題在轉:單機天花板在哪裡?會不會出現單點故障?流量是穩定成長還是會突然暴衝?錢要怎麼花比較划算?下面就用這幾個角度來看。
一、實務上怎麼評估?先看天花板、可用性、突發,再算成本
一般不會只拿「同容量誰便宜」來決定,而是會看這幾件事:
- 單機天花板:目標若是萬人同時在線(大促、熱門直播、萬人課程),單機再大都有上限——雲端單一 instance 通常到 32 核、64 核就封頂或貴到不划算,垂直擴充沒辦法支援那種規模,勢必要水平。你可以用前一篇提到的方式,先量出「現在這台滿載大概能撐多少人/多少 QPS」,當作單機天花板。
- 可用性(單點故障):只有一台後端,機器掛掉或維修,服務就全掛。多台+負載平衡,一台壞了還有其他台頂著,這是選水平很常見的理由,跟省不省錢無關。
- 突發流量:水平可以流量來時加機器、降時減機器;若為突發而垂直擴充(例如大促前升到 8 核 16G),大促結束、流量降下來,規格還在那裡,等於多付錢養用不到的容量。
- 成本:用你家雲端的價錢表和監控,粗估「每台多少錢、滿載大概能撐多少人」,再算出不同方案一個月大概要花多少、可以撐多久。若高規單機特別貴,同容量下水平可能反而省(有點像黃金交叉),可以當補充參考,但多數團隊是先看天花板與可用性、再看成本。
所以需要一套「什麼時候垂直、什麼時候水平」的判斷方式。
二、具體怎麼判斷
- 抓單機上限:查你家雲端單一 instance 最大規格(例如 32 核 64G),用監控或負載測試粗估「那台滿載時能撐多少 QPS 或同時在線」→ 這就是垂直的天花板。
- 比目標與時間:
- 目標容量已超過單機上限 → 只能水平。
- 目標還在單機內、但成長快 → 用「目前滿載 × 擴充倍率」當新容量,依每月成長率算「大概幾個月後會頂到單機上限」;例如現在滿載 200 人、你打算擴到能撐 400 人,每月成長 15%,大概 4~5 個月後又會碰到瓶頸,這時就要考慮提前改水平或把架構留好(分流、狀態、DB)。
流程一句話:單機上限 → 目標有沒有超過 → 沒超過的話多久會頂到 → 頂到時間若很近就選水平或提前準備。
三、實務上怎麼選
- 先選垂直:流量成長可預期、短期升級一兩次就夠、團隊小想少維運。例如 2 核 4G 升到 4 核 8G 撐過這波,很多早期服務這樣就夠,沒有錯。
- 選水平:目標超過單機上限、或很快會頂到、或有突發流量需求。選了就要在多台後端前面擺一層分流(負載平衡),實務上常用 Nginx 或雲端 LB——下一段談。
小明他們若決定「多加幾台後端」,接下來就要面對:誰來把請求分到各台?答案就是 Nginx(或雲端 LB)。
水平擴充時,前面要擺誰來分流?Nginx 與負載平衡
多加幾台後端之後,使用者還是只會打同一個網址(例如 api.course-platform.com)。必須有一個角色負責接收所有請求,再轉發到後面其中一台後端,否則不知道要打哪一台。這個角色就是負載平衡器(load balancer)。
Nginx 常被拿來做這件事:對外扮演反向代理(reverse proxy),對內把請求轉發到多台後端。使用者連到 Nginx,Nginx 再依照設定(例如 round-robin 輪流、或依當時連線數分配)把請求轉給某一台後端。這樣對外仍是一個網址,背後卻有多台機器在分攤流量。
實務上怎麼做?在 Nginx 的設定裡會有一個 upstream 區塊,列出後面幾台後端的位址與 port;在 server 區塊裡用 proxy_pass 指到這個 upstream。Nginx 就會把進來的請求轉發到 upstream 裡定義的其中一台。若用雲端服務(例如 AWS ALB、GCP Load Balancing),概念一樣:對外一個 endpoint,背後掛多台 instance,由雲端幫你做分流。
所以小明他們若選水平擴充,架構會變成:使用者 → Nginx(或雲端 LB)→ 多台後端。Nginx 在這裡的角色就是負載平衡與反向代理——對外一個入口,對內把流量分到多台後端。
選水平之後,會遇到的新問題(預告)
多加幾台後端、前面掛上 Nginx 之後,同一使用者的不同請求,可能會被分到不同的後端。例如第一次請求打到 A 台、第二次打到 B 台。若後端有在「自己機器上」記住使用者的登入狀態或購物車(Session),A 台記的 B 台沒有,使用者就會覺得「怎麼重新整理就登出了」「購物車有時有東西、有時沒有」。
這就是多台後端的狀態問題:每台各自記一份,沒有共用,就會亂。下一篇會談怎麼處理——例如把 Session 存到共用儲存(如 Redis),或把後端設計成無狀態、把狀態放在別的地方。這裡先建立「選水平擴充,就要一併考慮狀態怎麼放」的直覺。
小結
當單機快撐不住,可以垂直擴充(升級 CPU、記憶體)或水平擴充(多加幾台後端)。垂直簡單、有上限;水平彈性大、但要多做分流與狀態管理。若選水平,就要在多台後端前面擺負載平衡器,實務上常用 Nginx 做反向代理,把請求轉發到後面多台後端;對外一個網址,背後多台機器分攤流量。選水平之後,多台後端會帶來「狀態、Session 怎麼共用」的新問題,下一篇再談。我們下一篇見。