可伸縮Web架構的4個問題:瓶頸,CPU,數據庫,IO


在這篇文章中我將談到關於大規模網站架構擴展和性能方面的一些問題。
首先讓我們先來了解一些術語。稍後我將對Web應用擴展過程中所遇到的不同問題進行講解,例如:
 架構瓶頸
 數據庫擴展
 CPU消耗型應用
 IO消耗型應用
性能
Web系統的性能受多方面因素的影響,但大多數開發人員主要關心的是響應時間和可擴展性這兩方面。
響應時間
響應時間是指Web應用從收到請求到返回響應結果所花費的時間。而應用系統應該在可接受的時間範圍內返回響應結果,否則就不能算是一個性能良好的應用系統。
可擴展性
如果Web應用通過增加更多硬件可以使處理的請求數呈線性增長,那麼該應用是可擴展的。
擴展的方式可以分爲以下兩種:
1) 縱向擴展(垂直擴展):爲單臺機器增加CPU或者提高單臺機器CPU性能。
2) 橫向擴展(水平擴展):增加服務器數量
垂直擴展 VS 水平擴展
一般情況下水平擴展比垂直擴展更重要,主要是因爲普通硬件商品遠比需要特殊配置的硬件便宜(比如大型機);但是增強單個應用在一個硬件商品上處理的請求數同樣也是比較重要的。同時,一個應用系統在不降低響應時間的前提下,如果通過添加更多的資源能夠處理更多的請求,那麼這個系統表現良好。
響應時間 VS 可擴展性
在同一個應用中,響應時間和可擴展性並不總是能夠同時達到最好的效果。要麼應用程序有可接受的響應時間但是不能處理超過一定數量的請求;要麼應用程序可以處理大量請求,但是響應時間卻不盡如人意,甚至非常糟糕。因此,通常情況下我們需要在這兩個要素中尋求平衡點使我們的應用系統性能達到最佳狀態。
容量規劃
容量規劃需要我們根據產品期望的負載量來預估所需要的硬件數量。除了整體的預估外,這通常還包括使用更少硬件時系統的性能表現情況以及單臺機器下的性能的測試及評估。
架構擴展
如果Web應用的每一層在多層架構體系中都是可擴展的,那麼該應用也具有可擴展性(橫向擴展)。例如,如下圖所示,我們就可以通過增加額外的資源來實現應用層和數據庫層的線性擴展。


負載均衡器擴展
可以通過將DNS指向多個IP以及使用DNS輪循查找IP地址的方式來實現負載均衡器的橫向擴展。或者可以使用多級負載均衡,使上一級負載均衡器來分發至下一級負載均衡器,但使用多個負載均衡器的情況比較少,主要是由於Web容器一般可以處理幾千併發請求,而使用nginx或者HAProxy的單個負載均衡器可以處理超過20000的併發請求,因此單個負載均衡器完全可以代理多個web應用。
數據庫功能擴展
數據庫功能擴展是非常常用的方式,但是擴展數據庫功能(比如創建存儲過程或自定義函數)都會給數據層帶來額外開銷以及增加數據層的複雜性。
關係型數據庫
關係型數據庫可以通過主從同步的模式實現擴展,主庫以寫入數據爲主,從庫只做讀操作。但是,如果業務量比較大時主從同步模式所提供的擴展能力非常有限,此外,開發人員還需要通過數據庫拆分技術來進一步滿足業務需求。
NoSQL
CAP定理(譯者注:不熟悉的讀者可通過谷歌查閱)告訴我們一個應用不可能同時滿足一致性、可用性、分區容錯性三個要求。而NoSQL一般則是通過犧牲一定的一致性來獲得更高可用性以及更好的分區容錯性。
數據庫拆分
數據庫拆分可以垂直拆分和水平拆分:
 垂直拆分(Partitioning):根據領域模型概念的基礎可以將數據庫拆分爲幾個鬆耦合的子庫。例如,拆分爲消費者數據庫、產品數據庫。另一種垂直拆分數據庫的方式是將一個實體的一部分字段拆分出來作爲一個新數據庫,另一部分字段作爲另一個數據庫。例如,將消費者數據拆分爲消費者聯繫信息和訂單數據兩部分。
 水平拆分(Sharding):可以根據數據的離散屬性將數據進行水平分割。例如,消費者可以根據地域不同拆分爲美國消費者數據庫和歐洲消費者數據庫。
將數據庫從單個數據庫使用分區或者sharding拆分爲多個數據庫是一項非常有挑戰性的任務。
架構瓶頸
可擴展系統出現性能瓶頸的原因主要在於以下兩方面:
 中心化組件 應用中一個不可擴展的組件直接影響整個系統或者請求處理通道所能處理請求數的上限。
 高延遲組件 一個高延遲的組件會影響整個系統響應時間的下限,使整個系統響應時間更長。通常解決這個問題的辦法是使高延遲的組件作爲後臺任務線程或者使用異步隊列來解決。
CPU消耗型應用
如果一個應用的吞吐量受CPU的限制,那麼該應用就是CPU消耗型應用。此類引用通過增加CPU計算速度即可減少響應時間。
以下這些應用場景可能屬於CPU消耗性:
 需要計算或者處理數據而不需要做IO操作的應用(財務或者交易類系統)
 非常依賴緩存而且不做任何IO操作的應用
 異步(非阻塞)模型而且不需要等待外部資源的應用(被動應用或者使用NoJs的應用)
在以上使用場景中已經正常運行的應用,如果在一些應用場景中寫了糟糕的或者效率低下的代碼來對每次請求做大量額外的計算或者循環,那麼這些應用的CPU佔用率將非常高。但是通過分析應用可以很容易發現並修改效率低的問題。
IO消耗型應用
如果一個應用的吞吐量受IO或者網絡操作影響而且提升CPU計算速度並不能減少響應時間,那麼該應用即爲IO消耗型應用。大多數應用是IO消耗型應用主要是由於要做增、刪、改、查操作。而性能調優和對iO消耗型應用進行擴展也由於這些系統依賴於其他系統的下行流量變得非常困難。
以下這些應用場景可能是IO消耗性:
 依賴數據庫並進行增、刪、改、查操作的應用
 需要下行流量來完成本身操作的應用

譯者注:本文只是簡單提到可伸縮應用的主要問題以及所用到的技術,其中每一項展開來談都不是一兩篇文章可以講的完的。archleaner今後也將持續爲大家提供優質的技術文章。


1.本文由程序員學架構翻譯,由mathew同學校審;僅用於交流學習使用。

2.本文譯自Venkatesh CM在Architecture Issues Scaling Web Applications的博客。

3. 轉載請務必註明本文出自:程序員學架構(微信號:archleaner )

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章