在規劃一個雲端網站系統之前,首先要做的就是了解該系統會有多少使用量。基本上都是要先推估未來三年的可能使用量。假設如果這個系統可能有的資料量如下:
- 每個月會有1TB的新資料湧入網站,每筆寫入封包占1KB的資料量,且每個月有10億的寫入封包筆數。這樣預估三年累積下來就會有36TB的資料量(我們假設每一筆寫入封包都是全新資料,而不是部分內容更新。)。
- 假設每秒鐘平均需要處理有400筆寫入封包和4萬筆讀取封包(讀寫的比例為100:1)。
因為對一個網站來說,每秒鐘處理一個封包,就相當於每個月需要處理2500萬個封包。每秒400筆寫入封包就相當於每個月1億筆寫入封包量,每秒4萬筆寫入封包就相當於每個月10億筆讀取封包量。緊接著,根據預估的使用量來規畫需要的硬體設備,部署到雲端。早期在虛擬機器時代的步驟就是A到F的步驟,而在現在容器化的時代,就是步驟G。容器化時代的思維就只是把網站的功能再切割成更細微,劃分成更多層面來做管理。以下的文章敘述省略安全性的管理,因為我覺得那是另外一個議題。
1. 方案A - 基本配備
系統初期只有1到2個使用者,因此只需要一個最簡單的基本設備就可以了,就是一個網站伺服器搭配一個DNS服務。因此,使用者只要在雲端上建立一個虛擬主機,再搭配一個Storage,和資料庫(如MySQL)即可。記得要隨時監控系統狀態(如CPU,記憶體,IO,網路等),確認何時需要擴充設備。
初期的系統僅需要採取垂直擴充(Vertical Scaling)的方式,擴充硬體的大小即可(垂直擴充就是擴充硬體的大小,舉例將1Core的CPU增加成3Core的CPU。關於Scaling相關的議題之後,再補充介紹)。
2. 方案B - 增加Object Storage
當網站流量增加的時候,開始將資料庫中的靜態資料(如使用者的設定檔,JS,CSS,圖片和影片)轉移到放在物件導向的儲存設備(如AWS S3)。
使用像AWS RDS的服務來管理MySQL,做簡單的擴充性管理,或者配置在AWS多個Availability Zone上(AZ),當然多加設備就是多燒錢。
3. 方案C - 增加負載平衡策略
由於網站伺服器無法應付尖峰時間的流量,因此要採用水平擴充(Horizontal Scaling)的方式來處理尖峰時刻的流量(水平擴充就是增加硬體數目,如一台伺服器變三台伺服器)。這個時期需要做的處理如下:
- 配置網站伺服器在多個AZ中,分散網站的流量。
- 設定一個像AWS ELB或者是HAProxy那樣的負載平衡器(Load Balancer),設定讓配置在不同AZ的網站伺服器皆可服務使用者的流量。
- 增加多個MySQL資料庫的副本(Replica),並配置在不同AZ上來增加系統可用性,防止萬一有一個資料庫副本掛掉,還有其他的資料庫副本可以提供服務。
- 將網站切割成一個反向伺服器(Reverse Proxy)跟兩個應用伺服器(Application Servers)。其中,一個應用伺服器專門處理讀取的API,另一個處理寫入的API。
- 靜態的內容搬到像AWS CloudFront那樣的內容傳遞網路(Content Delivery Network)來減少負載跟減輕存取延遲。
4. 方案D - 改善資料庫讀取速度
- 增加像Elasticsearch那樣的記憶體快取(Cache)在減輕資料庫的負擔和降低存取延遲。
- 利用像AWS Autoscaling的水平自動擴充(Horizontal Autoscaling)服務,來動態根據目前流量增加網站伺服器數目,因應臨時大量的流量需求。
- 增加MySQL資料庫的讀取複本來減輕資料庫的讀取流量負擔。
5. 方案E - 導入自動化管理
- 利用水平自動擴充的方式和透過CloudWatch的監控,動態根據當前流量,自動增加或減少網站伺服器和應用伺服器的數目。當流量增加的時候,自動增加伺服器數目來提供服務給使用者;當流量減少的時候,自動減少伺服器數目來節省開機的成本(其實這個水很深阿><,哀)。
- 利用如Ansible那種部署應用服務的工具做自動化部屬。
6. 方案F - 改善資料庫寫入速度
- 當資料庫的資料越來越大,開始要把資料庫中的資料再作切割跟轉移。
- 擴充像Elaticsearch這樣記憶體快取系統的方式來減低讀取流量的負載。
- 把寫入應用程式伺服器在切分成同步和非同步兩種應用伺服器,並且增加像Kafka那樣的訊息處理系統來加快封包處理速度。
- 利用切片(Sharding)等資料庫水平擴充的技術來擴充資料庫。
- 將合適的資料轉移到更利於水平擴充的非關聯式資料庫(NoSQL)。
7. 方案G
- 轉移到像Kubernetes那種容器化的系統,根據網站各種應用程式的功能,將不同應用程式部署在不同的namespace上做管理。
- 好處是管理的粒度越小,因為將原本部署在虛擬機器(Virtual Machine,VM)上的應用程式切割成更小的容器(Container);但缺點就是更複雜。
- 想看看,假設原本網站部署在10台VM上,每台VM假設有10個應用程式,所以總用有100個應用程式。現在換成用Kuberntes做部署在5台VM上,100個應用程式就變成100個容器。表面上看起來比較省錢,因為原本要花10台VM的錢變成只要5台VM就好了,但卻變得比較難維護。
- 因為以前工程師只要系統有問題,就登入相關應用程式的VM去檢查哪邊有問題就好了。但在Kubernetes系統,100個應用程式副本是隨機分布在每個VM上,彼此透過網路互相溝通,而且我們又啟動自動化水平擴充功能和自動化垂直擴充的方式來管理應用。一但有狀況發生,問題發生的原因就變得更複雜了。
參考資料
- System design primer
- System design
- Awesome system design