架構即權衡
事物是發展變化的,事物的發展是一個過程。時間上,事物的發展過程呈現階段性特徵;空間上,每個階段必然有不同的具體業務場景。
故從時空觀來看,網站架構方法大致不外乎兩種:
-
時間上:分階段看待
- 空間上:分場景處理
對於架構而言,沒有銀彈,只有trade-off。架構師則需要階段性場景化思考,然後權衡利弊,解決問題。
問題描述
任何大的事物必然都是從小事物發展起來的,當系統業務足夠簡單時,實現一個網站架構只需要一些通用的解決方案,如早期的LAMP架構,如現今的雲開發模式以及無服務架構。
作為人與機器的『中間人』- 程序員,負責把業務需求轉換成業務代碼與數據。隨着業務的發展以及需求不斷迭代與豐富,網站系統的複雜度自然從低到高轉變,網站的量(包括用户量和數據量)從小到大,從大量到海量,網站的類型(包括用户操作類型與數據類型)從單純到豐富。程序員在負責『翻譯』工作的同時,則還需要解決這些增長過程中出現的各種問題,保證整個組織實現又好又快發展。
解決問題是工程師的天職,更是程序員的宿命。Ta需要解決當下業務發展中遇到的問題,更需要解決未來業務發展規模化的問題。
即程序員歸根結底解決的是變化這個命題,細分到具體操作層面也可以分為下面三類:
-
解決業務變化問題:
-
從簡單到複雜,保證系統高可用 - 分層&解耦&冗餘
-
從存量到增量,保證系統可伸縮與可擴展 - 集羣/分佈式/分佈式集羣
-
解決用户變化問題,保證系統高併發 - 單機C10K-》集羣-》分佈式-》分佈式集羣
-
解決數據變化問題:保證系統高性能 - 緩存
-
從量少到量多
- 從單一類型到混合類型
解決方法
拋開編程語言與具體框架的細節,這裏只討論方法。簡單的問題可單槍匹馬,複雜的問題則需要分而治之。下面將從分與治兩個方面來討論具體的網站架構方法。
1)分
空間上,分這個動作可以分為兩類:
-
垂直劃分:分層
- 水平劃分:分割
1.1)分層
面對複雜問題時,第一步要想到的就是分層。
當網站發展到一定規模,單一的通用架構已無法處理這種複雜性,這時架構分層不可避免。
分層的概念在網絡協議上表現的淋漓盡致,通過將一個數據傳輸任務劃分為多個層級,下層向上層提供完整抽象,每層各司其職。網站系統也可將系統在縱向維度上切分成幾個部分,每一部分專注於某一方面,職責相對單一,邏輯清晰,然後通過上層對下層的依賴和調用組成一個完整的系統。根據網站系統的職能,大致可以分為四層:
-
表示層:網站的UI展示,負責用户與網站系統的交互。
-
應用層:主要負責具體業務邏輯處理。調用下層服務實現業務需求。
-
服務層:負責為應用層提供細粒度的業務服務。
- 數據層:負責為服務層提供數據存儲與訪問。
1.2)分割
當網站規模進一步擴大,功能越發繁多複雜,服務和數據處理的種類也越來越多,這時針對每層進行更為細粒度的劃分-垂直分割勢在必行。如在服務層,可根據不同業務場景進行分割,如將整個電商服務拆分出訂單服務,支付服務,商品服務等;如在數據層,可根據數據類型將數據分為文本、圖片、視頻、日誌等類型數據,然後針對每一種類型的數據採用適合的存儲結構或服務:文本類型數據使用數據庫存儲;圖片/視頻使用CDN存儲;日誌類型數據使用ES存儲等等。
將這些不同功能/類型的服務/數據分割開來,封裝成高內聚低耦合的模塊單元,一方面有助於降低系統的複雜度,減少軟件的開發和維護成本;另一方面,也便於不同模塊的分佈式部署,提高網站的併發處理能力和可伸縮、可擴展能力。
2)治
分完之後下一步則是治之。
2.1)解耦
分層和分割之後的模塊間必然存在依賴關係,即必然存在耦合。解耦是一種理想狀態,理論上相互聯繫的模塊間耦合度不能為零,但是耦合度可以降低,即所謂的解耦。
2.1.1)異步化:時間形式上的解耦
耦合的模塊之間存在連接,有連接在某個時刻就可能會引起阻塞(存在等待的場景)。為了減少這種模塊之間阻塞問題,提高效率,可以將一個流程或一條業務線操作分成多個階段,每個階段之間通過共享數據(即消息隊列或緩衝區)的方式進行協作,這就是異步化。
異步架構是典型的生產者-消費者模式,兩者不存在直接調用,而是通過緩衝區進行通信,彼此功能實現可以隨意變化而不互相影響,這對大大提高了網站的性能與可擴展性。
2.1.2)分佈式:空間形式上的解耦
解耦是為了適應網站日益增長的複雜業務需求,解耦之後的下一步則是將切分後的模塊分佈式部署,即將不同模塊部署在不同的服務器上,通過遠程調用協同工作,這將進一步提高網站的性能與擴展性。
2.2)併發
用户量激增,網站併發成為瓶頸。
I/O多路複用解決了經典的C10K問題(如Nginx,Redis都是典型應用),此時我們不得不將目光從單機投向集羣,從集羣投向分佈式,從分佈式投向分佈式集羣,以尋求更大範圍的併發。
相對於單機,集羣提升了網站的可伸縮性(指通過不斷地向集羣中加入服務器的手段來緩解不斷上升的用户併發訪問壓力和不斷增長的數據存儲需求);分佈式(部署)提升了網站的可擴展性(指網站不需要任何改動或者很少改動既有業務功能就可以上線新的業務產品的能力)。在綜合了最優網絡I/O模型與分佈式和集羣的優勢下,網站的高併發成為可能。
注:解耦在降低系統複雜度的同時也為更好地系統實現高併發創造了條件:分佈式場景。
2.3)緩存
緩存的依據是網站訪問數據的特點大體呈現二八定律:80%的業務訪問集中在20%的數據上。所以,一旦遭遇網站的數據訪問性能問題時,首先想到的就是加緩存。
緩存的世界有這麼一句話:有數據的地方就可以有緩存。從這個角度講,再擴大一點範圍:凡是位於速度相差較大的兩種介質之間,用於協調兩者數據傳輸差異的結構,均可稱為緩存。按照這個概念,只有兩種介質之間存在傳輸速率差,速率較高的一方即可作為較低方的緩存。
在網站的世界,每一層皆可緩存。以PHP應用為例:底層有磁盤文件緩存、CPU緩存;應用層有Zend虛擬機緩存、APC緩存等;數據層有資源文件緩存(CDN)、數據緩存(如Redis/Memcache)等。
2.4)冗餘備份:有備無患
實現高可用網站架構的主要手段是:數據和服務的冗餘備份及失效轉移。有備則無患,如數據庫除了定期備份,存檔保持,實現冷備份之外,為了保證在線業務高可用,還需要對數據庫進行主從分離,實現同步實現熱備份。 一旦某些服務器宕機,就將服務切換到其他可用的服務器上,如果磁盤損壞,則從備份的磁盤讀取數據。
總結
本文介紹了網站架構中常用的一些方法論與手段,皆是從日常實際工作項目中的積累與沉澱,看上去有點理論有點虛,但十分有指導意義。軟件的世界裏沒有好壞,只有優劣,而架構師追求的永遠是業務上的性價比。