高流量網站架構的效能提升解決方案
這篇文章主要說明高流量(上千萬人)網站有哪些解決方案。
高流量網站所帶來的問題不外乎是網站反應時間會變得很慢甚至當機。
因此,可以”即時”與”不中斷”的服務便是高流量網站的挑戰。
每一種技術的背後都有優點與缺點,在採用每一種可行的技術前,
也要思考適不適合目前的情境。而非一昧的採用。
這篇文章廣泛的討論,當要擴充延伸網站的效能幾種可行的做法。
1. CDN (Content Delivery Network)
這裡引用中華電信的廣告文宣比較好理解,
使用 CDN相當於將網站效能的問題透過網路電信商來解決,
也就是原本網路基礎架構、網站伺服器快取, proxy等投資移轉到網路電信商,
對於中小企業或是臨時性的活動事件需要應付高流量網站來說,這是一個不錯的解決方案。
網路電信商會根據所要傳遞的網路內容,使用者所在區域,建置適當的網路架構、網站快取服務等。
2. Reverse Proxy
為什麼要用 Reverse Proxy? 主要是因為它可以提供:
- 負載平衡
- 快取
如果可以把網站流量分散到許多台網站伺服器,那麼就可以透過多台網站伺服器來提升效能。
另外,針對經常讀取的資料可以放在快取伺服器,也可以減少網站伺服器的負擔。
提到 Reverse Proxy 就不得不認識 NginX (讀音 Engine X,Engine去頭尾 “e”)
為什麼要多一個 “Reverse” Proxy呢?
這是瀏覽器到網站的 “Forward Proxy”,Proxy 轉送請求到後端的網站。
這種方案最大的缺點是瀏覽器端需要設定 proxy 的位置。在企業內部或許可行。
但是一般網際網路的網站,使用者瀏覽器比較不可能為了瀏覽特定網站而設定特殊的 proxy。執行上會有困難。
因此,出現 “Reverse Proxy”。瀏覽器不需要設定任何 proxy。
直接連接特定的網址之後,由該 proxy轉發該網址到後端對應的網站。
因為 proxy 與後端網站有相互轉換網址的動作,因此這樣的proxy 稱為 reverse Proxy。
在網際網路的網站中,多半採用的會是這樣的架構。
(Source: Stackoverflow)
小結, Reverse Proxy 都會提供下列功能
- Load Balance
- HTTP keepalive offload, caching, and compression
- Authentication, SSL
我們主要的目的就是將網站伺服器的負擔平均分散在各個網站伺服器上,
透過增加多台的網站伺服器的方式來增加網站服務的效能。
3. MemCached
網站內容的快取可以透過 Proxy (NginX)。相對來說,資料庫的資料快取可以透過 MemCached。
目的跟 Web Proxy 相同,MemCached 將經常讀取的資料快取在記憶體中,
可以減輕資料庫”讀取”的負擔,並且提供優異的讀取效能。
與 Web Proxy 很大的不同是,Web Proxy 背後的 Web site 之間不需要將資料相互同步”寫入”。
資料庫資料因為有 ACID 的問題,所以資料寫入時,資料庫間需要將資料相互同步。
因此,MemCached對於資料庫快取的資料,多半僅用在 “讀取” 而非”寫入”。
MemCached伺服器間通常相互獨立。
MemCached伺服器快取的資料內容通常依照 Consistent Hashing演算法決定,每台都不同。
資料讀取平均分在每一台MemCached中。
特別要強調的是 MemCached不是資料庫。僅適合用在將資料快取在記憶體中。不適合寫入資料或是存放資料。
(另外一個記憶體快取的替代方案是 redis)
4. Load Balance
Load Balance 主要透過平行處理的方式將負擔平行的分布到多台伺服器。
原本是一個人要做的事情,透過 10個人或是 100個人,事情就比較快可以完成。
Load Balance 對於每個伺服器獨立運作、伺服器間不需要資料相互同步的情況下特別有用。
例如:快取伺服器、網站伺服器等。都可以透過軟體或是硬體的 Load Balance 來達到負載平衡與效能的提升。
針對資料庫來說,一般而言,我們可以針對”讀取”的資料快取,再針對快取的資料做負載平衡。
為什麼”寫入”的資料不適合呢? 因為會有資料同步的問題與資料的不一致性。
當資料寫入時,相對要要同步資料到各個資料庫伺服器反而增加整體的網路與資料庫的負擔。
5. 非同步處理Message Queue
網站的效能會慢另外一個原因在於 “同時” 處理大量的使用者請求。
但是許多的情境不一定需要同時或是當下處理,如此一來可以透過”時間”來減緩伺服器所能處理的工作。
舉例來說,部落客發佈的文章,是否要即寫入資料庫 And 即時通知訪客有新文章呢?
其實這是可以分階段分時間進行的。
我們可以透過非同步處理,將文章先寫入緩衝Queue,
等到訪客登入或是拜訪時再通知有新文章。類似,電子郵件的概念。寄件者存放在信箱。
收件者等到上線收到信的時候,看到信件內容再進一步處理接下來的動作。
非同步處理比較知名的就是 ActiveMQ,ActiveMQ本身也具有彈性的延展性。
可以透過增加 ActiveMQ 伺服器來達到處理更多請求。
這個架構不儘可以應用在大型網站也可應用在一般的 Client/Server 企業應用系統架構。
透過彈性增加多台 ActiveMQ可以讓原本一台Server 所能支援的 Client 連線數量從 1000到 10000。
6. Web Server 與 Application Server 分離
將Web Server 與 Application Server 分離
讓Web Server 主要處理 HTML網頁
讓Application Server 主要處理商業邏輯與資料庫資料的存取
Application Server 有許多商業與昂貴的選擇,
筆者另外建議一個簡單的 Java Opensource “DropWizard”
DropWizard 提供一個簡單的架構框架,包含建立一個Http Web REST Service基本元件
- Jetty for HTTP
- Jersey for REST
- Jackson for JSON
7. NoSQL
使用關聯式資料庫的最大缺點在於讀取效能與未來資料表結構改變上比較沒有彈性。
相對的NoSQL可以提供優異的資料蒐尋與讀取、很方便的透過增加伺服器來做負載平衡、可以很彈性的定義資料結構。
哪些資料或是情境適合NoSQL 哪些適合 Rational SQL database ?
筆者認為比較簡單的思考是:
當該資料交易不需要嚴謹的”交易保護” Transaction 或是資料的一致性 “ACID” 那麼可以考慮使用 NoSQL
嚴謹的”交易保護”像是結帳金額,扣款餘額等,跟金錢有關的資訊內容,我們不希望在不同時間點看到的餘額會因為時間差或是資料同步而有所錯誤。
因此,其實日常生活大部分的資訊內容都是可以容許時間差(數分鐘或是數小時)或是甚至不需要納麼嚴謹的交易控制。
例如:部落格文章的更新、網站樣式的改版、新功能的上限、歷史購買紀錄等。
NoSQL 資料庫相對於關聯式資料庫在分散式資料處理上,NoSQL 相對可以容易的透過增加 Node 的方式擴充效能與平衡負載。
8. 資料庫Clustering
關聯式資料庫如果要做到Load Balance通常可以透過 Clustering 或是資料的複製來達成。
如下圖所示,Master/Slave的 Clustering。Master Database 資料會定期同步到 Slave Database。
Master Database 主要負責處理資料寫入與更新
Slave database 主要負責資料的讀取。
9. 資料的水平與垂直分割
對於關聯式資料庫來說,另一個可以分散資料庫負擔的方式就是對於資料進行分割。
切割資料的方式又可分為水平與垂直切割
水平切割指的是將資料表的資料依據特定的條件分割到許多不同的資料表。
例如下面的例子,用時間來切割
垂直切割指的是將整個功能切割。從前端網頁功能、應用服務、資料庫、資料等。
整體的切割。讓整個專案在執行上也可以比較彈性且獨立。
10. 前端網頁的設計
整體網站的效能可以大致分為前端與後端。後端包含資料庫、應用程式伺服器、網路等。
前端指的是網頁的呈現與反應時間。網頁是使用者最直接接觸的畫面。因此,網頁的設計有些基本的原則:
- JavaScript 放在最後,CSS放在最上面
- Minify JavaScript/CSS:也就是去除不必要的空白,可以減少檔案大小與下載的時間。通常程式完成後要上線前都會做這樣的動作。有許多免費的工具可以完成。
- 壓縮: 網站伺服器都可以設定將傳送的資料壓縮 gzip,節省網路頻寬
- PNG圖形檔壓縮:選用適當大小的圖形檔,用PNG圖形檔。
- 減少網路來回的請求:減少網站與用戶端往返來回的 request。例如使用 Image Map 會比用許多當圖來的有效率。因為Image Map 只會做一次的 http Request。
- 快取:透過設定 Http Header 快取,可以讓用戶端瀏覽器對於第二次讀取的資料進行快取。
- Ajax:非同步的網頁讀取動作。有部分的網頁變化可以直接在用戶端執行,不需要再次存取後端網站。
11. 商業邏輯
最後要提的是透過非技術方式解決。透過設定不同服務間的 SLA 也可以有效的減緩網站伺服器所面臨的效能問題。
舉例來說:
- 1000萬人同時間上網買票。可以設定為分區分時,讓上網購票的人數可以分散。不至於同一免內湧進1000萬人的狀況。
- 關閉不需要的服務。在特定時端時,可以關閉不需要的服務。
- Timeout。當服務無法即時回覆時,提醒使用者重新嘗試。多半的情況下重新嘗試一次可能就會恢復正常。因此使用者比較不會因為全面性的當機而受到困惱。
網站之所以無法負荷往往是因為在”同一時間內”湧入”大量的請求”到”同一台伺服器”,
因此只要適當的將下列原因分解、分時、分散、問題自然就可以解決了。
- 同一時間
- 使用者大量請求
- 同一台伺服器