花了幾個晚上看完了《大型網站技術架構》這本書,我的感受這本書的廣度還行,深度還有些欠缺(畢竟只有200頁左右)。可是做爲一個缺少大型網站技術的IT民工,看完一遍仍是頗有收穫的,至少對一個網站的技術演進、須要解決的問題有了一個全面的認識。文中也有一些做者我的的心得、感悟、總結,我以爲仍是很中肯的。html
在網上一搜,這本書的讀書筆記仍是不少的,而我本身仍是決定寫一篇讀書筆記,主要是爲了不本身忘得太快。筆記的內容並不徹底按照原書的內容,主要記錄的是我本身感興趣的部分。前端
本文地址:http://www.cnblogs.com/xybaby/p/8907880.html程序員
做者反覆在文中提到一個觀點:大型網站是根據業務需求逐步演化而來的,而不是設計出來的。web
不得不認可,互聯網行業發展到了今天,大魚吃小魚仍是很廣泛的,大公司的微創新能力分分鐘就能幹死一個小的項目,因此小公司須要足夠快的發展,不停的快速迭代與試錯。redis
下面是是一個演化的過程,圖片來自網絡。算法
在初始階段,訪問量並不大,因此應用程序、數據庫、文件等全部的資源都在一臺服務器上。數據庫
隨着業務的發展,就會發現一臺服務器抗不過來了,因此將應用服務器與數據(文件、數據庫)服務器分離。三臺服務器對硬件資源的要求各不相同:應用服務器須要更快的CPU,文件服務器須要更大的磁盤和帶寬,數據庫服務器須要更快速的磁盤和更大的內存。分離以後,三個服務器各司其職,也方便針對性的優化。後端
「世界上沒有什麼問題是加一級緩存解決不了的,若是有那就再加一級緩存」瀏覽器
緩存的使用無處不在,緩存的根本目的是加快訪問速度。當數據庫的訪問壓力過大的時候,就能夠考慮使用緩存了。網站使用的緩存能夠分爲兩種: 緩存在應用服務器上的本地緩存和緩存在專門的分佈式緩存服務器上的遠程緩存。緩存
隨着業務的發展,單個應用服務器必定會成爲瓶頸,應用服務器實現集羣是網站可伸縮集羣架構設計中較爲簡單成熟的一種。後面也會提到,將應用服務器設計爲無狀態的(沒有須要保存的上下文信息),就能夠經過增長機器,使用負載均衡來scale out。
即便使用了緩存,但在緩存未命中、或者緩存服務時效的狀況下,仍是須要訪問數據庫,這個時候就須要數據庫的讀寫分離:主庫提供寫操做,從庫提供讀服務。注意,在上圖中增長了一個數據訪問模塊,能夠對應用層透明數據庫的主從分離信息。
CDN和反向代理其實都是緩存,區別在於CDN 部署在網絡提供商的機房;而反向代理則部署在網站的中心機房。使用CDN 和反向代理的目的都是盡旱返回數據給用戶, 一方面加快用戶訪問速度,另外一方面也減輕後端服務器的負載壓力。
單個物理機的磁盤是有限的,單個關係數據庫的處理能力也是有上限的,因此須要分佈式文件存儲與分佈式數據庫。固然,也須要」統一數據訪問模塊「,使得應用層不用關心文件、數據的具體位置。值得一提的事,關係型數據庫自身並無很好的水平擴展方案,所以通常都須要一個數據庫代理層,如cobar、mycat。
web2.0的不少應用並必定適合用關係數據庫存儲,更加靈活的NoSql能更加方便的解決一些問題,並且NoSQL自然就支持分佈式。專門的搜索引擎在提供更優質服務的同時,也大大減輕了數據庫的壓力。
」
將一個網站拆分紅許多不一樣的應用, 每一個應用獨立部署維護。應用之間能夠經過一個超連接創建關係(在首頁上的導航連接每一個都指向不一樣的應用地址) ,也能夠經過消息隊列進行數據分發, 固然最多的仍是經過訪問同一個數據存儲系統來構成一個關聯的完整系統
既然每個應用系統都須要執行許多相同的業務操做, 好比用戶管理、商品管理等,那麼能夠將這些共用的業務提取出來,獨立部署。
經過服務的分佈式,各個應用能更好的獨立發展,實現了從依賴模塊到依賴服務的過渡。將通用的公共服務獨立出來,也方便作服務管控,好比對各個應用的服務請求進行監控,在高峯時期限制、關閉某些應用的訪問等。
這一部分是說大型網站須要解決的核心問題,以及解決這些問題的常規思路。
五個要點:性能,可用性,伸縮性,擴展性,安全
做者指出,不少時候你們都混淆了伸縮性(Scalability)與擴展性(Extensibility)。我之前也是把Scalability稱之爲擴展性,不過想一想,在咱們講代碼質量的時候,擴展性也是指Extensibility,之後仍是直接說這兩個英文單詞好了。
這幾點後面會詳細介紹
對模式的定義,書中描述得很好:
" 每個模式描述了一個在咱們周圍不斷重複發生的問題及該問題解決方案的核心。這樣, 你就能一次又一次地使用該方案而沒必要作重複工做" 。模式的關鍵在於模式的可重複性, 問題與場景的可重複性帶來解決方案的可重複使用。
用我本身的話來講,模式就是套路。這些模式,都是爲了達成上面提到的核心要素。那麼,有哪些模式呢
分層是企業應用系統中最多見的一種架構模式,將系統在橫向維度上切分紅幾個部分,每一個部分負責一部分相對比較單一的職責, 而後經過上層對下層的依賴和調用組成一個完整的系統。
在大型網站架構中也採用分層結構,將網主佔軟件系統分爲應用層、服務層、數據層。
分層的好處在於:解耦合,獨立發展,伸縮性,可擴展性。上面網站的進化史也凸出了分層的重要性。
可是分層架構也有一些挑戰, 就是必須合理規劃層次邊界和接口,在開發過程當中,嚴格遵循分層架構的約束, 禁止跨層次的調用( 應用層直接調用數據層)及逆向調用(數據層調用服務層, 或者服務層調用應用層)。
分層強調的是橫向切分,而分割是縱向切分, 上面網站進化史部分的業務拆分就包含了分割。
分割的目標是高內聚、低耦合的模塊單元
分層和分割的一個主要目的是分佈式部署,但分佈式也有本身的問題:網絡通訊帶來的性能問題,可用性,一致性與分佈式事務,系統維護管理複雜度。
一個機器解決不了的問題,就用幾個機器來解決,當服務無狀態的時候,經過往集羣增長機器就能解決大部分問題。對應網站進化史中「使用應用服務器集羣改善網站的併發處理能力」
緩存就是將數據存放在距離計算最近的位置以加快處理速度,同時大大減輕了數據提供者的壓力
大型網站架構設計在不少方面都使用了緩存設計:CDN、反向代理、本地緩存、分佈式緩存
異步是解耦合的一個重要手段,常見的生產者-消費者模型就是一個異步模式。
出了解耦合,異步還能提升系統可用性、加快響應速度、流量削峯
冗餘是系統可用性的重要保障,也是數據可靠性的重要手段
凡人老是會出這樣那樣的錯誤,能自動話的就要自動化。自動化大大解放了程序員、運維人員的生產力!
發佈過程自動化、自動化代碼管理、自動化測試、自動化安全檢測、自動化部署、自動化監控、自動化報警、自動化失效轉移、自動化失效恢復、自動化降級。
奧運精神:更快、更高、更強
技術人員對於性能的追求是無止境的。
性能,站在不一樣的角度,衡量指標是不同的:
用戶視角:響應時間,優化手段:(瀏覽器優化,頁面佈局,壓縮文件,http長連接),CND,反向代理
開發人員視角:系統延遲、吞吐量、穩定性。優化手段:緩存,異步,集羣,代碼優化
運維視角:基礎設施性能 資源利用率。優化手段:定製骨幹網絡、定製服務器,虛擬化
常見的衡量標準包括:響應時間、吞吐量、併發量。關於這些衡量標準,文中有一個很好的比喻:
系統吞吐量和系統併發數, 以及響應時間的關係能夠形象地理解爲高速公路的通行情況: 吞吐量是天天經過收費站的車輛數目(能夠換算成收費站收取的高速費) , 併發數是高速公路上的正在行駛的車輛數目,響應時間是車速。車輛不多時, 車速很快, 可是收到的高速費也相應較少; 隨着高速公路上車輛數目的增多,車速略受影響,可是收到的高速費增長很快; 隨着車輛的繼續增長,車速變得愈來愈慢,高速公路愈來愈堵,收費不增反降; 若是車流量繼續增長,超過某個極限後,任何偶然因素都會致使高速所有癱瘓, 車走不動,費固然也收不着,而高速公路成了停車場(資源耗盡)。
瀏覽器優化:減小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)須要解決的核心問題是一致性問題
失效轉移操做由三部分組成: 失效確認、訪問轉移、數據恢復。
上面描述了失效確認的兩種方法:控制中心經過心跳檢測存儲服務器的存活性;應用在訪問存儲服務失敗的時候通知控制中心檢測存儲服務存活性
網站的伸縮性是指不須要改變網站的軟硬件設計,僅僅經過改變部署的服務器數量就能夠擴大或者縮小網站的服務處理能力。
將應用層設計成無狀態,便可利用集羣 + 負載均衡來解決伸縮性問題。
關於負載均衡,我以前也寫過一篇文章《關於負載均衡的一切:總結與思考》介紹。
首先,緩存是有狀態的,分佈式緩存服務器集羣中不一樣服務器中緩存的數據各不相同,緩存訪問請求不能夠在緩存服務器集羣中的任意一臺處理,必須先找到緩存有須要數據的服務器,而後才能訪問。
若是緩存訪問被路由到了沒有緩存相關數據的服務器,那麼該訪問請求就會落地到數據庫,增長數據庫的壓力。所以,必須讓新上線的緩存服務器對整個分佈式緩存集羣影響最小,即緩存命中率越高越好。
在這個場景下,最好的負載均衡算法就是一致性hash
關係型數據庫,依賴於分佈式數據庫代理。而NoSQL數據庫產品都放棄了關係數據庫的兩大重要基礎: 以關係代數爲基礎的結構化查詢語言( SQL ) 和事務一致性保證( AClD )。而強化其餘一些大型網站更關注的特性: 高可用性和可伸縮性。
伸縮性總結:一個具備良好伸縮性架構設計的網站,其設計老是走在業務發展的前面, 在業務須要處理更多訪問和服務以前,就已經作好充足準備, 當業務須要時, 只須要購買或者租用服務器簡單部署實施就能夠。
設計網站可擴展架構的核心思想是模塊化, 並在此基礎之上, 下降模塊間的耦合性,提升模塊的複用性。
主要有分佈式消息隊列和分佈式服務。
分佈式消息隊列經過消息對象分解系統耦合性, 不一樣子系統處理同一個消息。
分佈式服務則經過接口分解系統輯合性, 不一樣子系統經過相同的接口描述進行服務調用。
縱向拆分: 將一個大應用拆分爲多個小應用, 若是新增業務較爲獨立, 那麼就直接將其設計部署爲一個獨立的Web 應用系統。
橫向拆分: 將複用的業務拆分出來, 獨立部署爲分佈式服務, 新增業務只須要調用這些分佈式服務, 不須要依賴具體的模塊代碼,便可快速搭建一個應用系統, 而模塊內業務邏輯變化的時候, 只要接口保持一致就不會影響業務程序和其餘模塊。
分佈式服務依賴於分佈式服務治理框架
這一起接觸甚少,還須要花點時間專門學習學習
服務治理框架的功能和特色:
服務註冊與發現
服務調用
負載均衡
失效轉移:分佈式服務框架支持服務提供者的失效轉移機制, 當某個服務實例不可用, 就將訪問切換到其餘服務實例上,以實現服務總體高可用。
高效遠程通訊
整合異構系統
對應用最小侵入
版本管理:分佈式服務框架須要支持服務多版本發佈, 服務提供者先升級接口發佈新版本的服務, 並同時提供舊版本的服務供請求者調用, 當請求者調用接口升級後才能夠關閉舊版本服務。
實時監控
所謂問題, 就是體驗一指望,當體驗不能知足指望, 就會以爲出了問題。消除問題有兩種手段: 改善休驗或者下降指望。
問題被發現,它只是問題發現者的問題,而不是問題擁有者的問題,若是想要解決一個問題,就必須提出這個問題,讓問題的擁有者知道問題的存在。
提出問題Tips:
1. 把" 個人問題" 表述成" 咱們的問題"2. 給上司提封閉式問題, 給下屬提開放式問題3. 指出問題而不是批評人4. 用贊同的方式提出問題 --》不是說 你這裏有問題,而是說,方案不錯,我有一點疑問(建議)