高負載網站的技術架構 (Java為例)

高負載網站的技術架構 (Java為例)

這篇文章主要說明當一個網站從數千人的線上使用者到數千萬人的連線使用者時,

有哪些架構上可以調整的部分,以符合高流量的網站需求?

網站可以達到數千萬人的使用者所面臨的技術上的挑戰不外乎是:Availability, Scalability, performance等

我們會說明幾種在不需要大改設計的情況下,可以彈性調整的作法。

這些做法不一定要到數千萬人,小型的網站有部分模組有效能瓶頸時也可以參考。

網站的非功能性目標

一個網站除了提供商業功能之外,還會提供非功能性目標。

效能

網站可以提供許多使用者同步平行處理請求。這種情況特別發生在高鐵的線上車票購買的情況。

在短時間內,有大量的使用者連線上限購買,造成系統瞬間的高負載,無法處理的情況下當機。

Availability

就是 99.999%或是 99.99%的目標。

要達到這個目標就必須要做到 “容錯” 與負載平衡 Load Balance,

透過多台伺服器相互提供存取,相互備份資料,

當其中一台伺服器無法存取時,其他伺服器還可以運作。

“多台伺服器”相互提供資源的方式其實是高流量網站的 一個重要觀念!

不管是資料庫伺服器、網站伺服器、Web Logic Server、Cache Server等

都透過這個方法 “多台伺服器” 相互負載平衡,相互提供資源達到高可用性與高效能。

另外,軟體流程也必須整體的規劃,

例如自動化佈署、自動化測試、漸進式的上限佈署、自動化監控、自動化除錯與復原等

Scalability (螞蟻雄兵)

所設計的架構是否可以很容易的透過增加伺服器來達到效能的提升。

之前提到,”多台伺服器”相互提供資源的方式其實是高流量網站的 一個重要觀念!

不管是資料庫伺服器、網站伺服器、Web Logic Server、Cache Server等

例如,當資料庫有效能瓶頸的時候,是否可以很容易的增加 Cache Server 或是資料庫伺服器就解決效能的問題?

筆者簡稱 “螞蟻雄兵”

這就是整體設計架構 Scalability 要考量的範圍。筆者認為這也是最重要的部分。

因為,只要設計架構可以彈性的調整增加伺服器,

未來遇到效能不足或是有臨時性大量流量處理的需求時,

就可以輕易的可以透過增加伺服器的方式將整體的效能提升。

要達到這個螞蟻雄兵的目標有幾種不同的架構可以採用。

Extendability

擴充性。這部分指的是新功能的增加不會影響既有或是現在的設計。

要達到這個目標就必須靠 Message Queue 與分散式服務 SOA的架構來達成。

接著讓我們介紹幾種可以採用的方法來達上述目標。

Load Balance / Proxy

最常見的就是透過 Load Balance的方式將網站伺服器的負載平均的分擔到各個網站伺服器。

未來如果網站伺服器有效能瓶頸,可以輕易的增加網站伺服器來提升整體的使用者請求。

1. 設計上要注意的是 load Balance 的routing 機制是否可以做到真正的”平均”

2. 在未來新增網站伺服器之後,該 Load Balance分配request的方式是否平均

3. 因為 Http Request 為 stateless,  因此當有 Session 需要處理的時候(例如,購物車),設計上就必須保持該 session 的完整性。

(通常可以透過 Cookie 或是 Session Database 處理來保有該 session。或是有些 Load Balance會對於 session 有 Tag 的機制,保有該session 的完整狀態。)

通常 Load Balance 本身都會有HTTP Proxy的功能,透過 Http Proxy Server快取,也可以分攤網站伺服器的負荷。

 

前端網頁的設計

網站包含前端網頁、商業邏輯與資料庫資料存取等部分。前端網頁通常是使用者體驗最直接的操作介面。

因此,前端網頁的設計有些重要的設計要點,可以讓網頁的效能更好。

 

減少 Http Request 的請求:

如果可以在一次 Http Request 完成就不需要分為多次,減少網路往返的時間。比較常見的例子像是許多JavaScript。

或是許多的 CSS、甚至是圖檔等。這些都可以合併成一個檔案,減少網路往返的存取。

善用瀏覽器快取:

適當的設定 Expires將靜態的網路資源,例如 JavaScript, CSS 或是圖檔,透過瀏覽器的快取存在使用者端,

也可以有效的提升效能。當有需要更新  JavaScript檔案的時候可以透過更新檔名的方式實現。

啟用壓縮 :

一般的網站伺服器都可以設定啟用壓縮 gzip。壓縮可以有效的將 JavaScript 、圖檔、CSS檔案變小,減少網路傳輸的時間。

JavaScritp放在最下面,CSS放在最上面:

因為瀏覽器在解析網頁的時候,如果遇到下載JavaScript時,會阻擋接下來的網頁下載動作。

因此先將整個網頁下載呈現,之後再載入JavaScript 會有比較好的使用者體驗。

減少DNS:

有些網頁的內容會到許多不同的 DNS domain 存取。每一次的DNS query 都會額外產生網路查詢時間。

建議可以透過CDN有效的將網頁內容透過CDN來存取。

 

多層式的架構 + MemCached

這也是另外一種螞蟻雄兵。分為網站伺服器、Application Server (商業邏輯)與資料庫。

其中Memcached 是什麼呢? 簡單來說它是一種記憶體的快取伺服器!

Memcached是用來分擔存取資料庫的負荷。如果資料可以在 Memcached取得,就不需要到資料庫存取了。

由於 Memcached是 Key/Value pair 的結構,沒有SQL 的ACID, 沒有 Isolation, 沒有Trasaction, Lock等,

加上Memcached是利用記憶體快取,所以 Memcached存取的速度很快,

對於只要”讀取”資料來說,效能遠比MySQL or MSSQL 關聯式資料庫好。

下圖的架構,進一步把讀取與寫入的操作分離。讓Memcached提供讀取。只有在寫入的動作時候,才需要存取後端資料庫。

memcached 由於使用容易,可以很容易的將資料快取成 Key/Value,也可以很容易的安裝,

因此memcached被廣泛的運用在分散式資料處理。http://memcached.org/

1. 資料快取到哪一台快取伺服器呢?

假設我們佈署三台快取記憶體伺服器,因為有三台的關係,所以我們簡單的用取3餘數的方式將資料分配到對應的快取記憶體伺服器

  • (3, A) => 3 Mod 3 => 資料分配到第0 台
  • (4, B) => 4 Mod 3 => 資料分配到第1 台
  • (5, C) => 5 Mod 3 => 資料分配到第2 台

但是,經過時間與使用者的增加,我們必須要多增加一台快取記憶體伺服器時,如果還是用這樣的演算法取4的餘數,

會導致之前已經快取的資料,之後會取不到!而且必須重新快取。

  • (3, A) => 3 Mod 4 => 資料分配到第3 台
  • (4, B) => 4 Mod 4 => 資料分配到第0 台
  • (5, C) => 5 Mod 4 => 資料分配到第1 台

看出來問題了嗎? 同樣的資料,但是因為加入新的快取記憶體伺服器後,之前快取的資料取不到,而且會被重新快取到別的伺服器。

因此,設計上要注意這樣快取資料分配到哪一台伺服器的問題。解決這個問題的方法就是 Consistent Hash 演算法。

2. 快取記憶體不適用在Session 的儲存

之前提到購物車會需要儲存使用者相關的訊息,實務上通常透過 Cookie或是額外的 Session Server 來處理,

這樣的 session 資訊不適合透過快取記憶體伺服器儲存。因為這樣的資料通常在使用者登出之後,該資料就失效。

而且這樣的資料會被重複讀取的機率很低。

3. 快取記憶體伺服器間不需相互溝通

快取記憶體伺服器盡量保持獨立。彼此不要相互溝通。這樣一來,才可保持整體快取記憶體伺服器使用上的彈性。

 

非同步作業

提到非同步作業就必須認識 ActiveMQ http://activemq.apache.org/

為什麼需要非同步作業呢? 我們知道如果要同步處理所有的請求是很耗資源的,但是想想有許多的情境是不需要同步或是即時處理的。

例如,部落格資訊。寫完一篇部落格之後,該部落格文章可以被放到訊息Queue中

等到有讀者來讀取的時候,讀者再到該Queue去讀取就可以。

透過 Queue的機制,可以做到非同步作業。因此可以有效降低同步處理的負荷。

 

資料庫的 Clustering

 

資料庫的 proxy

Database Proxy解決方案主要是要將資料庫的負擔平均分配到其他資料庫。

以SQLrelay為例子,SQLRelay就是其中一種資料庫proxy。可以將資料庫的佈署架構如下:

  • 資料庫的proxy
  • 資料的水平分割
  • 資料的垂直分割

類似的解決方案有 MaxScale, Amoeba, SQLrelay, MySQL Proxy

NoSQL的採用

 

SOA/ Web Application 訊息間的傳遞

 http://www.dropwizard.io/

 

  • Jetty for HTTP
  • Jersey for REST
  • Jackson for JSON

 

商業邏輯

除了透過技術上解決之外,還可以透過其他比較非技術的方式解決。

分級管理:例如火車開放訂購的時間,可以依據路線或是地區分時來開放購買。如此一來就不會大量湧入許多的人”同時”上線購買。

Timeout: 可以設定一定時間內就間該連線中斷。使用者通常只要重試一次就好。也不會導致所有人都不能使用或是當機。

關閉部分功能:在特定時段的使用有些功能可以暫時關閉減少伺服器負擔。例如:資料的備份、防毒軟體、使用者備份、帳號密碼重新設定等功能。

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *