1. 程式人生 > >大型網站技術架構:摘要與讀書筆記

大型網站技術架構:摘要與讀書筆記

思想 發展 感覺 物理 消息隊列 高可用架構 小時 整體 年度

  花了幾個晚上看完了《大型網站技術架構》這本書,個人感覺這本書的廣度還行,深度還有些欠缺(畢竟只有200頁左右)。但是作為一個缺乏大型網站技術的IT民工,看完一遍還是很有收獲的,至少對一個網站的技術演進、需要解決的問題有了一個全面的認識。文中也有一些作者個人的心得、感悟、總結,我覺得還是很中肯的。

  在網上一搜,這本書的讀書筆記還是很多的,而我自己還是決定寫一篇讀書筆記,主要是為了避免自己忘得太快。筆記的內容並不完全按照原書的內容,主要記錄的是我自己感興趣的部分。

  本文地址:http://www.cnblogs.com/xybaby/p/8907880.html

一個網站的進化史

  作者反復在文中提到一個觀點:大型網站是根據業務需求逐步演化而來的,而不是設計出來的

  不得不承認,互聯網行業發展到了今天,大魚吃小魚還是很普遍的,大公司的微創新能力分分鐘就能幹死一個小的項目,所以小公司需要足夠快的發展,不停的快速叠代與試錯。

  下面是是一個演化的過程,圖片來自網絡。

初始階段的網站架構

技術分享圖片

  在初始階段,訪問量並不大,所以應用程序、數據庫、文件等所有的資源都在一臺服務器上。

應用服務和數據服務分離

技術分享圖片

  隨著業務的發展,就會發現一臺服務器抗不過來了,所以將應用服務器與數據(文件、數據庫)服務器分離。三臺服務器對硬件資源的要求各不相同:應用服務器需要更快的CPU,文件服務器需要更大的磁盤和帶寬,數據庫服務器需要更快速的磁盤和更大的內存。分離之後,三個服務器各司其職,也方便針對性的優化。

使用緩存改善網站性能

技術分享圖片

  “世界上沒有什麽問題是加一級緩存解決不了的,如果有那就再加一級緩存”

  緩存的使用無處不在,緩存的根本目的是加快訪問速度。當數據庫的訪問壓力過大的時候,就可以考慮使用緩存了。網站使用的緩存可以分為兩種: 緩存在應用服務器上的本地緩存和緩存在專門的分布式緩存服務器上的遠程緩存。

使用應用服務器集群改善網站的並發處理能力

  技術分享圖片

  

  隨著業務的發展,單個應用服務器一定會成為瓶頸,應用服務器實現集群是網站可伸縮集群架構設計中較為簡單成熟的一種。後面也會提到,將應用服務器設計為無狀態的(沒有需要保存的上下文信息),就可以通過增加機器,使用負載均衡來scale out。

數據庫讀寫分離

  技術分享圖片

  即使使用了緩存,但在緩存未命中、或者緩存服務時效的情況下,還是需要訪問數據庫,這個時候就需要數據庫的讀寫分離:主庫提供寫操作,從庫提供讀服務。註意,在上圖中增加了一個數據訪問模塊,可以對應用層透明數據庫的主從分離信息。

使用反向代理和CDN 加速網站晌應

技術分享圖片

  CDN和反向代理其實都是緩存,區別在於CDN 部署在網絡提供商的機房;而反向代理則部署在網站的中心機房。使用CDN 和反向代理的目的都是盡旱返回數據給用戶, 一方面加快用戶訪問速度,另一方面也減輕後端服務器的負載壓力。

使用分布式文件系統和分布式數據庫系統

  技術分享圖片

  單個物理機的磁盤是有限的,單個關系數據庫的處理能力也是有上限的,所以需要分布式文件存儲與分布式數據庫。當然,也需要”統一數據訪問模塊“,使得應用層不用關心文件、數據的具體位置。值得一提的事,關系型數據庫自身並沒有很好的水平擴展方案,因此一般都需要一個數據庫代理層,如cobar、mycat。

使用NoSQL 和搜索引擎

 技術分享圖片

  web2.0的很多應用並一定適合用關系數據庫存儲,更加靈活的NoSql能更加方便的解決一些問題,而且NoSQL天然就支持分布式。專門的搜索引擎在提供更優質服務的同時,也大大減輕了數據庫的壓力。

業務拆分

  技術分享圖片

  將一個網站拆分成許多不同的應用, 每個應用獨立部署維護。應用之間可以通過一個超鏈接建立關系(在首頁上的導航鏈接每個都指向不同的應用地址) ,也可以通過消息隊列進行數據分發, 當然最多的還是通過訪問同一個數據存儲系統來構成一個關聯的完整系統

分布式服務

  技術分享圖片

  既然每一個應用系統都需要執行許多相同的業務操作, 比如用戶管理、商品管理等,那麽可以將這些共用的業務提取出來,獨立部署

  通過服務的分布式,各個應用能更好的獨立發展,實現了從依賴模塊到依賴服務的過渡。將通用的公共服務獨立出來,也方便做服務管控,比如對各個應用的服務請求進行監控,在高峰時期限制、關閉某些應用的訪問等。

大型網站架構模式與核心要素

  這一部分是說大型網站需要解決的核心問題,以及解決這些問題的常規思路。

核心要素

  五個要點:性能,可用性,伸縮性,擴展性,安全

  作者指出,很多時候大家都混淆了伸縮性(Scalability)與擴展性(Extensibility)。我以前也是把Scalability稱之為擴展性,不過想想,在我們講代碼質量的時候,擴展性也是指Extensibility,以後還是直接說這兩個英文單詞好了。

  這幾點後面會詳細介紹

網站架構模式

  對模式的定義,書中描述得很好:

  " 每一個模式描述了一個在我們周圍不斷重復發生的問題及該問題解決方案的核心。這樣, 你就能一次又一次地使用該方案而不必做重復工作" 。模式的關鍵在於模式的可重復性, 問題與場景的可重復性帶來解決方案的可重復使用

  用我自己的話來說,模式就是套路。這些模式,都是為了達成上面提到的核心要素。那麽,有哪些模式呢

分層

  分層是企業應用系統中最常見的一種架構模式,將系統在橫向維度上切分成幾個部分,每個部分負責一部分相對比較單一的職責, 然後通過上層對下層的依賴和調用組成一個完整的系統。

  在大型網站架構中也采用分層結構,將網主占軟件系統分為應用層、服務層、數據層。

  分層的好處在於:解耦合,獨立發展,伸縮性,可擴展性。上面網站的進化史也凸出了分層的重要性。

  但是分層架構也有一些挑戰, 就是必須合理規劃層次邊界和接口,在開發過程中,嚴格遵循分層架構的約束, 禁止跨層次的調用( 應用層直接調用數據層)及逆向調用(數據層調用服務層, 或者服務層調用應用層)。

分割

  分層強調的是橫向切分,而分割是縱向切分, 上面網站進化史部分的業務拆分就包含了分割。

  分割的目標是高內聚、低耦合的模塊單元

分布式

  分層和分割的一個主要目的是分布式部署,但分布式也有自己的問題:網絡通信帶來的性能問題,可用性,一致性與分布式事務,系統維護管理復雜度。

集群

  一個機器解決不了的問題,就用幾個機器來解決,當服務無狀態的時候,通過往集群增加機器就能解決大部分問題。對應網站進化史中“使用應用服務器集群改善網站的並發處理能力”

緩存

  緩存就是將數據存放在距離計算最近的位置以加快處理速度,同時大大減輕了數據提供者的壓力

  大型網站架構設計在很多方面都使用了緩存設計:CDN、反向代理、本地緩存、分布式緩存

異步

  異步是解耦合的一個重要手段,常見的生產者-消費者模型就是一個異步模式。

  出了解耦合,異步還能提高系統可用性、加快響應速度、流量削峰

冗余

  冗余是系統可用性的重要保障,也是數據可靠性的重要手段

自動化

  凡人總是會出這樣那樣的錯誤,能自動話的就要自動化。自動化大大解放了程序員、運維人員的生產力!

  發布過程自動化、自動化代碼管理、自動化測試、自動化安全檢測、自動化部署、自動化監控、自動化報警、自動化失效轉移、自動化失效恢復、自動化降級。

性能

  奧運精神:更快、更高、更強

  技術分享圖片

  技術人員對於性能的追求是無止境的。

  性能,站在不同的角度,衡量指標是不一樣的:

  • 用戶視角:響應時間,優化手段:(瀏覽器優化,頁面布局,壓縮文件,http長鏈接),CND,反向代理

  • 開發人員視角:系統延遲、吞吐量、穩定性。優化手段:緩存,異步,集群,代碼優化

  • 運維視角:基礎設施性能 資源利用率。優化手段:定制骨幹網絡、定制服務器,虛擬化

  常見的衡量標準包括:響應時間、吞吐量、並發量。關於這些衡量標準,文中有一個很好的比喻:

  系統吞吐量和系統並發數, 以及響應時間的關系可以形象地理解為高速公路的通行狀況: 吞吐量是每天通過收費站的車輛數目(可以換算成收費站收取的高速費) , 並發數是高速公路上的正在行駛的車輛數目,響應時間是車速。車輛很少時, 車速很快, 但是收到的高速費也相應較少; 隨著高速公路上車輛數目的增多,車速略受影響,但是收到的高速費增加很快; 隨著車輛的繼續增加,車速變得越來越慢,高速公路越來越堵,收費不增反降; 如果車流量繼續增加,超過某個極限後,任何偶然因素都會導致高速全部癱瘓, 車走不動,費當然也收不著,而高速公路成了停車場(資源耗盡)。

web前端性能優化

  瀏覽器優化:減少http請求,瀏覽器緩存,壓縮。CDN優化,反應代理

應用服務器性能優化

  四招:緩存、集群、異步、代碼優化

緩存

  首先自然是緩存

  網站性能優化第一定律: 優先考慮使用緩存優化性能。

  使用緩存,需要考慮的是緩存置換與一致性問題,其中緩存一致性問題也是分布式系統中需要解決的一個問題,主要的解決方法有租期和版本號。

  並不是所有的場合都適合緩存,如頻繁修改的數據、沒有熱點訪問的數據。

  緩存的可用性:理論上不能完全依靠,但事實上盡可能高可用,否則數據庫宕機導致系統不可用。因此緩存服務器也要納入監控,盡量高可用。

  緩存穿透:如果因為不恰當的業務、或者惡意攻擊持續高並發地請求某個不存在的數據,由於緩存沒有保存該數據, 所有的請求都會落到數據庫上,會對數據庫造成很大壓力,甚至崩橫。一個簡單的對策是將不存在的數據也緩存起來(其value 值為null )。

代碼優化

多線程

  為什麽要使用多線程,IO阻塞 與 多核CPU

  理想的load 是: 即沒有進程(線程)等待,也沒有CPU空閑

  啟動線程數= [任務執行時間/ (任務執行時間-10 等待時間)J xCPU 內核數

資源復用

  這個很常見,各種池(pool):線程池、連接池

高可用

  網站年度可用性指標= ( 1-網站不可用時間/年度總時間) x lOO%

  業界通常用N個9來衡量系統的可用性。如,2 個9 是基本可用, 網站年度不可用時間小於8 8 小時; 3 個9是較高可用, 網站年度不可用時間小於9 小時; 4 個9 是具有自動恢復能力的高可用,網站年度不可用時間小於53 分鐘; 5 個9 是極高可用性,網站年度不可用時間小於5 分鐘。

  可用性是大型網站的命脈,是否可用,用戶是可以立刻感知到的,短暫的不可用也會帶來巨大的損失。這也是為什麽大型網站在面對CAP問題時,更看重A(avalibility)的原因。

  高可用架構的主要手段是數據和服務的冗余備份及失效轉移

  在分層的網絡架構中,通過保證每一層的高可用,就實現了整個系統的高可用。而每一層又有自己的高可用手段

應用層高可用

  位於應用層的服務器通常為了應對高並發的訪問請求,會通過負載均衡設備將一組服務器組成一個集群共同對外提供服務,當負載均衡設備通過心跳檢測等手段監控到某臺應用服務器不可用時,就將其從集群列表中剔除,並將請求分發到集群中其他可用的服務器上,使整個集群保持可用,從而實現應用高可用。

  應用層的高可用很容易,因為應用服務器很多時候是無狀態的。

  但是也有時候需要有維護的數據,如session,這樣就不能將一個請求路由到任意的應用服務器。要解決session的問題,有以下幾種方法:

  • session綁定:利用負載均衡的源地址Hash 算法實現,負載均衡服務器總是將來源於同一IP 的請求分發到同一臺服務器上

  • 用cookie記錄session:Cookie是存放在客戶端(瀏覽器)的,在每次訪問的時候帶上cookie裏面的信息即可

  • 專門的session服務器:將應用服務器的狀態分離, 分為無狀態的應用服務器和有狀態的Session。簡單的方法是利用分布式緩存、數據庫(redis)來實現Session服務器的功能

服務層的高可用

  服務層的高可用也是利用集群,不過需要借助分布式服務調用框架。

  服務層的服務器被應用層通過分布式服務調用框架訪問,分布式服務調用框架會在應用層客戶端程序中實現軟件負載均衡, 並通過服務註冊中心對提供服務的服務器進行心跳檢測,發現有服務不可用,立即通知客戶端程序修改服務訪問列表,剔除不可用的服務器。

  為了保證服務層的高可用,可以采用以下策略

  • 分層管理

  • 超時設置

  • 異步調用

  • 服務降級,包括:拒絕服務,高峰時段,拒絕低優先級應用的訪問;關閉服務,關閉某些不重要的功能

  • 冪等性設計,方便失敗時重試

數據層的高可用

  包括分布式文件系統與分布式數據庫,核心都是冗余加失效轉移。

  冗余(復制集、replica)需要解決的核心問題是一致性問題

  失效轉移操作由三部分組成: 失效確認、訪問轉移、數據恢復。

  技術分享圖片

  上面描述了失效確認的兩種方法:控制中心通過心跳檢測存儲服務器的存活性;應用在訪問存儲服務失敗的時候通知控制中心檢測存儲服務存活性

伸縮性(Scalability)

  網站的伸縮性是指不需要改變網站的軟硬件設計,僅僅通過改變部署的服務器數量就可以擴大或者縮小網站的服務處理能力。

應用層的伸縮性

  將應用層設計成無狀態,即可利用集群 + 負載均衡來解決伸縮性問題。

  關於負載均衡,我之前也寫過一篇文章《關於負載均衡的一切:總結與思考》介紹。

緩存的伸縮性

  首先,緩存是有狀態的,分布式緩存服務器集群中不同服務器中緩存的數據各不相同,緩存訪問請求不可以在緩存服務器集群中的任意一臺處理,必須先找到緩存有需要數據的服務器,然後才能訪問。

  如果緩存訪問被路由到了沒有緩存相關數據的服務器,那麽該訪問請求就會落地到數據庫,增加數據庫的壓力。因此,必須讓新上線的緩存服務器對整個分布式緩存集群影響最小,即緩存命中率越高越好。

  在這個場景下,最好的負載均衡算法就是一致性hash

數據層的伸縮性

  關系型數據庫,依賴於分布式數據庫代理。而NoSQL數據庫產品都放棄了關系數據庫的兩大重要基礎: 以關系代數為基礎的結構化查詢語言( SQL ) 和事務一致性保證( AClD )。而強化其他一些大型網站更關註的特性: 高可用性和可伸縮性。

  伸縮性總結:一個具有良好伸縮性架構設計的網站,其設計總是走在業務發展的前面, 在業務需要處理更多訪問和服務之前,就已經做好充足準備, 當業務需要時, 只需要購買或者租用服務器簡單部署實施就可以。

可擴展性(Extensibility)

  設計網站可擴展架構的核心思想是模塊化, 並在此基礎之上, 降低模塊間的耦合性,提高模塊的復用性。

  主要有分布式消息隊列和分布式服務。

  分布式消息隊列通過消息對象分解系統耦合性, 不同子系統處理同一個消息。

  分布式服務則通過接口分解系統輯合性, 不同子系統通過相同的接口描述進行服務調用。

分布式服務

  縱向拆分: 將一個大應用拆分為多個小應用, 如果新增業務較為獨立, 那麽就直接將其設計部署為一個獨立的Web 應用系統。

  橫向拆分: 將復用的業務拆分出來, 獨立部署為分布式服務, 新增業務只需要調用這些分布式服務, 不需要依賴具體的模塊代碼,即可快速搭建一個應用系統, 而模塊內業務邏輯變化的時候, 只要接口保持一致就不會影響業務程序和其他模塊。

  分布式服務依賴於分布式服務治理框架

分布式服務治理框架

  這一塊兒接觸甚少,還需要花點時間專門學習學習

  技術分享圖片

  服務治理框架的功能和特點:

  • 服務註冊與發現

  • 服務調用

  • 負載均衡

  • 失效轉移:分布式服務框架支持服務提供者的失效轉移機制, 當某個服務實例不可用, 就將訪問切換到其他服務實例上,以實現服務整體高可用。

  • 高效遠程通信

  • 整合異構系統

  • 對應用最小侵入

  • 版本管理:分布式服務框架需要支持服務多版本發布, 服務提供者先升級接口發布新版本的服務, 並同時提供舊版本的服務供請求者調用, 當請求者調用接口升級後才可以關閉舊版本服務。

  • 實時監控

Others

  所謂問題, 就是體驗一期望,當體驗不能滿足期望, 就會覺得出了問題。消除問題有兩種手段: 改善休驗或者降低期望。

  問題被發現,它只是問題發現者的問題,而不是問題擁有者的問題,如果想要解決一個問題,就必須提出這個問題,讓問題的擁有者知道問題的存在。

  提出問題Tips:

1. 把" 我的問題" 表述成" 我們的問題"
2. 給上司提封閉式問題, 給下屬提開放式問題
3. 指出問題而不是批評人
4. 用贊同的方式提出問題 --》不是說 你這裏有問題,而是說,方案不錯,我有一點疑問(建議)

大型網站技術架構:摘要與讀書筆記