大型網站架構優化
- 初始階段

- 應用服務和數據服務分離

- 使用緩存改善網站性能

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

- 數據庫讀寫分離

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

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

- 使用NoSQL和搜索引擎

- 業務拆分

- 分布式服務

大型網站架構演化的價值觀
- 技術的核心價值是隨網站所需靈活應對
- 技術發展的主要力量是網站的業務發展
設計誤區
- 一味追隨大公司的解決方案
- 為了技術而技術
- 企圖用技術解決所有問題
大型網站架構模式
-
分層-橫向
-
分割-縱向
- 將不同的功能和服務分割,包裝成高內聚低耦合的模塊單元
-
分布式
切分后的模塊便于分布式部署,即將不同的模塊部署在不同的服務器上,通過遠程調用協同工作
- 分布式應用和服務
- 分布式靜態資源
- 分布式數據和存儲
-
分布式計算
- 分布式配置
- 分布式鎖
- 分布式文件
-
集群
將多臺服務器部署相同應用構成一個集群,通過負載均衡設備共同對外提供服務
-
緩存
- CDN
-
反向代理
前端架構的一部分,用戶請求最先訪問。這里緩存網站的靜態資源,無需將請求繼續轉發給應用服務就能返回給用戶
- 本地緩存
- 分布式緩存
-
異步
非同步調用、解耦、隊列。異步架構是典型的生產者消費者模式。
- 提供系統可用性
- 加快網站響應速度
- 消除并發訪問高峰
-
冗余(避免宕機情況)
- 訪問和負載很小的服務也必須部署至少兩臺服務器構成一個集群,通過冗余實現服務高可用
- 數據庫除了定期備份,存檔保存,實現冷備份外,還要對數據庫進行主從分離,實時同步實現熱備份
- 全球范圍內部署災難數據中心,抵御地震等不可抗力導致的網站癱瘓
-
自動化
- 發布過程自動化
- 自動化代碼管理
- 自動化測試
- 自動化安全檢測
- 自動化部署
- 自動化監控
- 自動化報警
- 自動化失效轉移
- 自動化失效恢復
- 自動化降級
- 自動化分配資源
- 安全
應用

大型網站架構核心架構要素
-
性能
- 優化手段(CDN、反向代理、本地緩存、分布式緩存、異步、集群、代碼層面_多線程等、數據庫優化、NOSQL)
- 性能指標(響應事件、TPS、系統性能計數器等)
通過監控這些指標可以分析系統瓶頸,預測網站容量,并對異常指標進行報警,保障系統可用性
- 要考慮在高并發訪問情況下,超出負載設計能力的情況下可能會出現的性能問題。網站需要長時間持續運行,還必須保證系統在持續運行且訪問壓力不均勻的情況下保持穩定的性能特性
-
可用性
- 排除故障時間,即總可用時間
一些知名大型網站可以做到4個9以上的可用性,即可用性超過99.99%
- 高可用設計目標即當服務器宕機的時候,服務或者應用依然可用
-
網站高可用的主要手段是冗余
- 應用服務器通過負載均衡設備組成集群
- 存儲服務需要對數據實時備份
- 需要質量保證。通過預發布驗證、自動化測試、自動化發布、灰度發布等手段,減少故障引入線上環境的可能
- 衡量一個系統架構設計是否滿足高可用的目標,就是假設系統中任何一臺或者多臺服務器宕機時以及出現各種不可預期的問題時,系統整體是否依然可用
-
伸縮性
- 所謂伸縮性即指通過不斷向集群中加入服務器的手段來緩解不斷上升的用戶并發壓力和不斷增長的數據存儲需求
- 衡量架構伸縮性的主要標準 就是是否可以用多臺服務器構建集群,是否容易向集群中增加新的服務器。加入新的服務器后是否可以提供和原來的服務器無差別的服務。集群中可容納的總的服務器數量是否有限制。
- 應用服務器集群,只有服務器上不保存數據,所有的服務器都是對等的。通過使用合適的負載均衡設備就可以向集群中不斷加入服務器
- 對于緩存服務器集群,加入新的服務器可能會導致緩存路由失效,進而導致集群中的大部分緩存數據都無法訪問。需要改進緩存路由算法保證緩存數據的可訪問性。
- 關系數據庫雖然支持數據復制,主從熱備等機制,但是很難做到大規模集群的可伸縮性,可通過如路由分區等手段將部署有多個數據庫的服務器組成一個集群。
- 大部分NoSQL數據庫產品先天即為海量數據而生,其對伸縮性的支持通常都非常好
-
擴展性
- 衡量網站架構擴展性好壞的主要標準就是網站增加新的業務產品時,是否可以實現對現有產品透明無影響,不需要任何改動或者很少改動既有業務功能就可以上線新產品。不同產品之間是否很少耦合,一個產品改動對其他產品無影響,其他產品和功能不需要受牽連進行改動
-
網站可伸縮架構的主要手段
-
事件驅動框架
-
分布式服務
- 將業務和可復用服務分離開來,通過分布式服務框架調用
-
安全性
- 保護網站不受惡意訪問和攻擊
- 保護網站的重要數據不被竊取
- 衡量網站安全架構的標準就是針對現存和潛在的各種攻擊與竊密手段,是否有可靠的應對策略
瞬時響應:網站的高性能架構
網站性能測試
-
從用戶角度的網站性能
- 包括用戶計算機和網站服務器通信的時間、網站服務器處理的時間、用戶計算機瀏覽器構造請求解析響應數據的時間
- 實踐中,可使用一些前端架構優化手段,如優化頁面HTML樣式,利用瀏覽器端的并發和異步特性、調整瀏覽器緩存策略、使用CDN、反向代理等
-
開發人員視角的網站性能
- 開發人員關注的主要是應用程序本身及其相關子系統的性能,包括響應延遲、系統吞吐量、并發處理能力、系統穩定性等技術指標。
- 主要的優化手段有使用緩存加速數據讀取、使用集群提高吞吐能力、使用異步消息加快請求響應及實現削峰、使用代碼優化手段改善程序性能
-
運維人員視角的網站性能
- 運維人員更關注基礎設施性能和資源利用率,如網絡運營商的帶寬能力、服務器硬件的配置、數據中心網絡架構、服務器和網絡帶寬的資源利用率等。
- 主要優化手段有建設優化骨干網、使用高性價比定制服務器、利用虛擬技術優化資源利用等
性能測試指標
-
響應時間
- 指應用執行一個操作需要的時間,包括從發出請求開始到收到最后響應數據所需要的時間。
- 響應時間是系統最重要的性能指標,直觀的反應了系統的“快慢”

- 測試程序通過模擬應用程序,記錄收到響應和發出請求之間的時間差來計算系統響應時間。但是記錄及獲取系統時間這個操作也需要花費一定的時間,如果測試目標操作本身需要花費的時間極少,比如幾微妙,那么測試程序就無法測試得到系統的響應時間
- 實踐中通常采用的辦法是重復請求,比如一個請求操作重復執行一萬次,測試一萬次執行需要的總響應時間之和,然后除以一萬,得到單次請求的響應時間
-
并發數
- 指系統能夠同時處理請求的數目,這個數字也反映了系統的負載特性。對于網站而言,并發數即網站并發用戶數,指同時提交請求的用戶數目
- 網站用戶數 > 網站在線用戶數 > 網站并發用戶數
- 測試程序通過多線程模擬并發用戶的辦法來測試系統的并發處理能力,為了真實模擬用戶行為,測試程序并非啟動多線程然后不停的發送請求,而是在兩次請求之間加上一個隨機等待時間,即思考時間
-
吞吐量
- 指單位時間內系統處理的請求數量,體現系統的整體處理能力
- 對于網站,可以用“請求數/秒”、”頁面數/秒“、”訪問人數/天“、”處理的業務數/小時“等來衡量
- TPS(每秒事務數)是吞吐量的一個常用量化指標,此外還有HPS(每秒HTTP請求數)、QPS(每秒查詢數)等
- 在系統并發數由小逐漸增加的過程中(這個過程也伴隨著服務系統資源消耗逐漸增加),系統吞吐量先是逐漸增加,達到一個極限后,隨著并發數的增加反而下降,達到系統崩潰點后,系統資源耗盡,吞吐量為0
- 這個過程中,響應時間則是先保持小幅上升,到達吞吐量極限后,快速上升,到達系統崩潰點后,系統失去響應。
-
形象理解
- 吞吐量是每天通過收費站的車輛數目
- 并發數是高速公路上正在行駛的車輛數目
- 響應時間是車速
- 車輛很少時,車速很快,但是通過收費站的車輛也較少
- 隨著高速公路上車輛數目的增多,車速略受影響,但是通過收費站的車輛增加很快
- 隨著車輛的繼續增加,車速變的越來越慢,高速公路越來越堵,通過收費站的車輛不增反降
- 如果車流量繼續增加,超過某個極限后,任何偶然因素都會導致高速全部癱瘓,車走不通,也不會有車通過收費站,而高速公路成了停車場,資源耗盡
- 網站性能優化的目的,處理改善用戶體驗的響應時間,還要盡量提高系統吞吐量,最大限度利用服務器資源
-
性能計數器
- 它是描述服務器或者操作系統性能的一些數據指標、包括SystemLoad、對象與線程數、內存使用、CPU使用、磁盤與網絡I/O等指標。這些指標也是系統監控的重要參數,對這些指標設置報警閥值,當監控系統發現性能計數器超過閥值時,就向運維和開發人員報警,及時發現處理系統異常
- System Load即系統負載,只當前正在被CPU執行和等待被CPU執行的進程數目總和,是反映系統忙閑程度的重要指標。多核CPU的情況下,完美情況是所有CPU都在使用,沒有進程在等待處理,所以Load的理想值是CPU的數目。當Load值低于CPU數目的時候,表示CPU有空閑,資源存在浪費;當Load值高于CPU數目的時候,表示進程在排隊等待CPU調度,表示系統資源不足,影響程序的執行性能。Linux下使用top命令查看,該值表示最近1分鐘、10分鐘、15分鐘的運行隊列平均進程數
性能測試方法
-
性能測試
- 以系統設計初期規劃的性能指標為預期目標,對系統不斷施加壓力,驗證系統在資源可接受范圍內,是否達到性能預期
-
負載測試
- 對系統不斷的增加并發請求以增加系統壓力,直到系統的某項或多項性能指標達到安全臨界值,如某種資源已經呈飽和狀態,這時繼續對系統施加壓力,系統的處理能力不但不能提高反而會下降
-
壓力測試
- 超過安全負載的情況下,對系統持續施加壓力,直到系統崩潰或不能再處理任何請求,以此獲得系統最大壓力承受能力
-
穩定性測試
- 被測試系統在特定硬件、軟件、網絡環境條件下,給系統加載一定業務壓力,使系統運行一段較長時間,以此檢測系統是否穩定。在不同生成環境、不同時間點的請求壓力是不均勻的,呈波浪特性,因為為了更好的模擬生產環境,穩定性測試也應不均勻地對系統施加壓力
-
性能測試是一個不斷對系統增加訪問壓力,以獲得系統性能指標、最大負載能力、最大壓力承受能力的過程。所謂的增加訪問壓力,在系統測試環境中,就是不斷增加測試程序的并發請求數,一般說來,性能測試遵循拋物線規律:
- 橫坐標表示消耗的系統資源,縱坐標表示系統處理能力,即吞吐量
- 開始階段,隨著并發請求數目的增加,系統使用較少的資源就達到較好的處理能力(a~b)段,這一段是網站的日常運行區間,網站的絕大部分訪問負載壓力都集中在這一段區間,被稱作性能測試
- 隨著壓力的測試增加,系統處理能力變緩,直到達到一個最大值c點,這是系統的最大負載點,這一階段被稱作負載測試,測試目標是評估系統因為突發事件超出日常訪問壓力的情況下保證系統正常運行情況下能夠承受的最大訪問負載壓力
- 超過這個點后,再增加壓力,系統的處理能力反而下降,而資源消耗卻更多,直到資源消耗達到極限d,這個點可以看做是系統的崩潰點,超過這個點繼續增大并發請求數目,系統不能再處理任何請求,這一段被稱作壓力測試,測試目標是評估可能導致系統崩潰的最大訪問負載壓力
-
性能測試反映的是系統在實際生產環境中使用時,隨著用戶并發訪問數量的增加,系統的處理能力。與性能曲線相對應的是用戶訪問的等待時間(系統響應時間),如下:
- 在日常運行期間,可以獲得最好的用戶響應時間,隨著并發用戶數的增加,響應延遲越來越大,直到系統崩潰,用戶失去響應
性能測試報告
- 測試結果報告應能夠反映上述性能測試曲線的規律,閱讀者可以得到系統性能是否滿足設計目標和業務要求、系統最大負載能力、系統最大壓力承受能力等重要信息,如

性能優化策略
-
性能分析
- 大型網站結構復雜,用戶從瀏覽器發出請求直到數據庫完成操作事務,中間需要經過很多環節,如果測試或者用戶報告網站響應緩慢,存在性能問題,必須對請求經歷的各個環節進行分析,排查可能出現性能瓶頸的地方,定位問題
- 排查一個網站的性能瓶頸和排查一個程序的性能瓶頸的手法基本相同:檢查請求處理的各個環節的日志,分析哪個環節響應時間不合理、超過預期;然后檢查監控數據,分析影響性能的主要因素是內存、磁盤、網絡還是CPU,是代碼問題還是架構設計不合理或者系統資源確實不足
-
性能優化
-
定位產生性能問題的基本原因后,就需要進行性能優化
- Web前端性能優化
- 應用服務器性能優化
- 存儲服務器性能優化
Web前端性能優化
-
瀏覽器訪問優化
-
減少http請求
-
使用瀏覽器緩存
- 設置http頭中cache-control和expires的屬性,設定瀏覽器緩存
- 靜態資源文件變化->生成一個新的文件
- 使用瀏覽器緩存策略的網站在更新靜態資源時應采用批量更新的方法以免用戶瀏覽器突然大量緩存失效,集中更新緩存,造成服務器負載驟增、網絡堵塞的情況
-
啟用壓縮
- gzip
- 壓縮對服務器和瀏覽器產生一定的壓力,在通信帶寬良好而服務器資源不足的情況要權衡考慮
-
CSS放在頁面最上面、JavaScript放在頁面最下方
- 瀏覽器會在下載完全部css之后才對整個頁面進行渲染,所以最好放在頁面最上面讓瀏覽器盡快下載css
- 瀏覽器在加載javascript后立即執行有可能會阻塞整個頁面,造成頁面顯示緩慢,所以最好放在頁面最下面
- 如果頁面解析時就需要用到javascript,這時放在底部就不合適了
-
減少cookie傳輸
- cookie因包含在每次請求和響應中,太大的cookie會驗證影響數據傳輸
- 對于某些靜態資源的訪問,如css,script等,發送cookie沒有意義,可考慮靜態資源使用獨立域名訪問,避免請求靜態資源時發送cookie,減少cookie傳輸的次數
-
CDN加速
- 本質仍然是一個緩存,而且將數據緩存在離用戶最近的地方
- CDN部署在網絡運營商的機房,這些運營商又是終端用戶的網絡服務提供商,用戶請求路由的第一跳就達到了CDN服務器->有緩存->直接返回給瀏覽器->最短路徑返回響應
- CDN能夠緩存的一般是靜態資源
-
反向代理
- 傳統代理服務器位于瀏覽器一側,代理瀏覽器將http請求發送到互聯網上
- 反向代理服務器位于網站機房一側,代理網站web服務器接收http請求
- 反向代理服務器也具有保護網站安全的作用
- 除了安全功能,代理服務器也可以通過配置緩存功能加速web請求。當用戶第一次訪問靜態內容,靜態內容就被緩存在反向代理服務器上
- 有些網站也會把動態內容也緩存在代理服務器上,如熱門詞條,當這些動態內容有變化時通過內部通知機制通知反向代理緩存失效,反向代理會重新加載最新的動態內容再次緩存起來
- 反向代理也可以實現負載均衡的功能,通過負載均衡構建的應用集群可以提高系統總體處理能力
應用服務器性能優化
-
分布式緩存
- 網站性能優化第一定律:優先考慮使用緩存優化性能
- 緩存的基本原理-hash->hashcode->索引下標
- 網站數據通常遵循28定律,即80%的訪問落在20%的數據上,因為利用hash和內存的高效訪問屬性,將這20%的數據緩存起來,可很好的改善系統性能,提高數據讀取速度,減低存儲訪問壓力
- 合理使用緩存,如過分依賴低可用的緩存系統,不恰當的使用緩存的訪問特性等
- 頻繁修改的數據,一般說來,數據的讀寫比在2:1以上,即寫入一次緩存,在數據更新前至少讀取兩次,緩存才有意義
- 沒有熱點的訪問,如果應用系統訪問數據沒有熱點,緩存就沒有意義。因為緩存使用內存作為存儲,內存資源寶貴而有限,不可能將所有數據都緩存起來,只能將最新訪問的數據緩存起來,而將歷史數據清理出緩存
- 數據不一致與臟讀,通常會對緩存的數據設置失效時間,一旦超過失效時間,就要從數據庫中重新加載。應用要容忍一定時間的數據不一致,如賣家已經編輯了商品屬性,但是需要過一段時間才能被買家看到。還有一種策略是數據更新時立即更新緩存,不過這也會帶來更多系統開銷和事務一致性的問題
-
緩存可用性,緩存數據丟失或者緩存不可用不會影響到應用程序的處理,其可以從數據庫直接獲取數據。當緩存服務器崩潰時,數據庫會因為完全不能承受如此大的壓力而宕機,即緩存雪崩。
- 緩存熱備等手段提高緩存可用性,當某臺緩存服務器宕機時將緩存訪問切換到熱備服務器上。但這種設計顯然有違緩存的初衷,緩存根本就不應該被當做一個可靠的數據源來使用
- 通過分布式緩存服務器集群,將緩存數據分不到集群多臺服務器上可在一定程度上改善緩存的可用行。當一臺緩存服務器宕機的時候,只有部分緩存數據丟失,重新從數據庫加載這部分數據不會對數據庫產生很大影響。
-
landon:從這個例子引入了兩種分布式集群的做法
- 將總體數據分別劃分到分布式子服務器,一臺掛掉不會影響其他(緩存的設計)
- 水平擴展,所有的分布式子服務器邏輯全部一致,一臺掛掉不會影響所有(應用服務器的設計)
- 當然也有如一致性hash的算法,也可以動態的增加或減少機器
- 緩存預熱,緩存存放的是熱點數據,熱點數據又是緩存系統利用lru對不斷訪問的數據篩選淘汰出來的,這個過程需要花費較長的時間。新啟動的緩存系統如果沒有任何數據,在重新緩存數據的過程中,系統的系統和數據庫負擔都不好->在緩存系統啟動的時候就把熱點數據加載好
- 緩存穿透,如因為不恰當的業務或者惡意攻擊持續高并發的請求某個不存在的數據,由于緩存沒有保存該數據,所有的請求都會落到數據庫上,會到數據庫造成很大壓力->簡單的對策是將不存在的數據也緩存起來,value為null
-
分布式緩存架構
-
JBoss Cache
- 需要更新同步的分布式緩存
- 該分布式緩存在集群中所有服務器中保存相同的緩存數據
- 當某臺服務器有緩存更新的時候,會通知集群中其他機器更新緩存數據或者清除緩存數據
- 其通常將應用程序和緩存部署在同一臺服務器上,應用程序可以從本地快速獲取緩存數據,不過這種方式受限于內存。另外當集群規模較大時,緩存更新信息需要同步到集群中所有機器,代價驚人。所以大型網站很少使用

-
Memcached
- 不互相通信的分布式緩存
- 大型網站需要緩存的數據量一般都很大龐大
- Memcached采用一種集中式的緩存集群管理,也被稱作互不通信的分布式架構方式
- 緩存與應用分離部署,緩存系統部署在一組專門的服務器上,應用程序通過一致性hash等路由算法選擇緩存服務器遠程遠程訪問緩存數據
- 緩存服務器之間不通信,緩存集群的規模可以很容易的實現擴容,具有良好的可伸縮性

-
Memcached
- 簡單的通訊協議-基于文本的自定義協議:命令關鍵字+命令操作數,如get ,可以看到這個redis很像,所以后續很多NoSQL產品都借鑒了或直接支持這套協議
- 豐富的客戶端程序,幾乎支持所有主流的網站編程語言
- 高性能的網絡通信,其服務端通信模塊基于libevent,一個基于事件觸發的網絡通信程序庫
- 高效的內存管理-固定空間分配(解決內存碎片問題)-LRU算法
- 互不通信的服務器集群架構:客戶端路由一致性hash算法成為數據存儲伸縮性架構設計的經典范式;也正是集群內服務器互不通信使得集群可以做到幾乎不限制的線性伸縮
-
異步操作
- 使用消息隊列將調用異步化

- 注意由于數據寫入消息隊列后立即返回給有用戶,數據在后續的業務校驗寫數據庫等操作可能是失敗,因此在使用消息隊列進行業務異步處理后,需要適當的修改業務流程進行配合。如訂單提交后,訂單數據寫入消息隊列,不能立即返回用戶訂單提交成功,需要在消息隊列的訂單消費者進程真正處理該訂單甚至商品出庫后再通過郵件等通知用戶訂單成功
- 任何可以晚點做的事情都應該晚點再做
-
使用集群
- 使用負載均衡技術為一個應用構建一個由多臺服務器組成的服務器集群,將并發請求分發到多臺服務器上處理
-
代碼優化
-
多線程
- 從資源利用的角度看,使用多線程的原因主要有兩個:IO阻塞和多CPU
- 假設服務器上執行的都是相同類型任務:啟動線程數=[任務執行時間/(任務執行時間-IO等待時間)] * CPU內核數;如果是cpu計算型任務,那么線程數最多不超過CPU內核數,因為啟動再多線程,cpu也來不及調度;而如果是任務需要等待磁盤操作,網絡響應,那么啟動多線程有助于提高任務并發度,提高系統吞吐能力,改善系統性能
-
注意線程安全問題
- 將對象設計為無狀態對象
- 使用局部對象
- 并發訪問資源使用鎖
-
資源復用
-
數據結構
- hash散列算法Time33算法:hash(i)=hash(i-1) * 33 + str[i]
- 某些相似字符串hashcode比較接近->字符串取信息指紋->再對指紋求hashcode
- 原始字符串->MD5->信息指紋->hash計算->hashcode
-
垃圾回收
- 理解垃圾回收機制
- 根據系統業務特點和對象生命周期,合理設置jvm參數等->盡量減少full gc
存儲性能優化
- 機械硬盤 vs. 固定硬盤
-
B+樹(關系數據庫) vs. LSM樹(許多NoSQL產品)
- LSM-Tree (Log-Structured Merge-Tree)
-
RAID(實現數據在多塊磁盤上的并發讀寫和數據備份) vs. HDFS(Hadoop分布式文件系統,可配合MapReduce)
- 磁盤陣列(Redundant Arrays of Independent Disks,RAID)
- Raid0、Raid1、Raid10、Raid3、Raid5、Raid6、
- Raid技術可以通過已經實現,也可通過軟件實現,該技術在傳統關系數據庫及文件系統中影響比較廣泛,但大型網站比較喜歡使用NOSQL及分布式文件系統
- HDFS中,系統在整個存儲集群中的多臺服務器上進行數據并發讀寫和備份,可以看做在服務器集群規模上實現了類似Raid的功能
小結
- 網站性能對最終用戶而言是一種主觀感受,性能優化的最終目的就是改善用戶的體驗,使他們感覺網站很快。離開這個目的,追求技術上的所謂高性能,是舍本逐末,沒有多大意義
- 用戶體驗的快或是慢,可以通過技術手段改善,也可以通過優化交互體驗改善
- 技術是為業務服務,技術選型和架構決策依賴業務規則,離開業務發展的支撐和驅動,技術走不遠,甚至會走迷路
- 前沿技術總是出現在前沿業務領域
萬無一失:網站的高可用架構
網站可用性的度量與考核
-
網站可用性度量
-
業界通常用多少個9來衡量網站的可用性
- QQ的可用性是4個9,即QQ服務99.99%可用,這意味著QQ服務要保證其在所有運行時間中,只有0.01%的時間不可用,即一年中大約最多53分鐘不可用
- 網站不可用時間(故障時間)= 故障修復時間點-故障發現(報告)時間點
- 網站年度可用性指標=(1-網站不可用時間/年度總時間) * 100%
- 對于大多數網站而言,2個9是基本可用;3個9是較高可用;4個9是具有自動恢復能力的高可用;5個9是極高可用性(年度不可用時間小于5分鐘)
-
網站可用性考核
- 可用性指標是網站架構設計的重要指標,對外是服務承諾,對內是考核指標。具體每個工程師的考核,更多的是使用故障分

高可用的網站架構
- 網站的高可用架構設計的主要目的就是保證服務器硬件故障時服務依然可用、數據依然保存并能夠被訪問
- 實現高可用架構的主要手段是數據和服務的冗余備份及失效轉移
-
一個典型的網站通常遵循如下的基本分層架構模型
- 典型的分層模型是三層,即應用層、服務層、數據層
- 應用層主要負責具體業務邏輯處理;服務層主要負責提供可復用的服務;數據層負責數據的存儲與訪問等
- 中小型網站在具體部署時通常將應用層和服務層部署在一起,而數據層則另外部署,而這也是網站架構演化的第一步
-
復雜的大型網站架構中,劃分的粒度會更小、更詳細、結構更加復雜,服務器規模更加龐大,但通常還是能夠把這些服務器劃分到這三層中:
- 應用層的服務器通常為了應對高并發的訪問請求,會通過負載均衡設備將一組服務器組成一個集群共同對外提供服務。負載均衡設備通過心跳檢測等手段監控某臺應用服務器不可用時就將其從集群列表中剔除并將請求轉發到集群中其他可用的服務器上,使整個集群保持可用,從而實現高可用
- 位于服務層的服務器情況和應用層的服務器類似,也是通過集群方式實現高可用,只是這些服務器被應用層通過分布式服務框架調用,分布式服務調用框架會在應用層客戶端程序中實現軟件負載均衡,并通過服務注冊中心對外提供服務的服務器進行心跳檢測,發現有服務不可用,立即通知客戶端程序修改服務訪問列表,剔除不可用的服務器
- 數據服務器上存儲這數據,為了保證服務器宕機時數據不丟失,數據訪問服務不中斷,需要在數據寫入時進行數據同步復制,將數據寫入多臺服務器上,實現數據冗余備份。當數據服務器宕機時,應用程序將訪問切換到有備份數據的服務器上
- 網站升級的頻率較高,如大型網站一周發布一次。每次網站發布都需要關閉服務,重新部署系統,整個過程相當于服務器宕機。因此網站的可用性架構設計不但要考慮實際的硬件故障引起的宕機,還要考慮網站升級發布引起的宕機而后者更加頻率,不能因為系統可以接受偶爾的停機故障將降低可用性設計的標準
高可用的應用
- 應用層主要處理網站應用的業務邏輯,因為有時也被稱為業務邏輯層->應用的一個顯著特點是應用的無狀態性
- 所謂無狀態的應用是指應用服務器不保存業務的上下文信息,而僅根據每次請求提交的數據進行相應的業務邏輯處理,多個服務實例(服務器)之間完全對等,請求提交到任意服務器,處理結果都是完全一樣的
-
通過負載均衡進行無狀態服務的失效轉移
- 負載均衡,顧名思義,主要使用在業務量和數據量較高的情況下,當單臺服務器不足以承擔所有的負載壓力時,通過負載均衡手段,將流量和數據分攤到一個集群組成的多臺服務器上,以提高整體的負載處理能力
- 目前不管是開源免費的負載均衡軟件還是昂貴的負載均衡硬件,都提供失效功能
- 在網站應用中,當集群中的服務是無狀態對等時,負載均衡可以起到事實上高可用的作用

- 當Web服務器集群中的服務器都可用時,負載均衡服務器會把用戶發送的訪問請求分發到任意一臺服務器上進行處理,而當10.0.0.1宕機時,負載均衡服務器通過心跳檢測機制發現服務器失去響應,就會把它從服務器列表中刪除,從而請求發送到其他服務器上,這些服務器是完全一樣的,請求在任何一臺服務器中處理都不會影響最終的結果
- 由于負載均衡在應用層實際起到了系統高可用的作用,因為即使某個應用訪問量非常少,只用 一臺服務器提供服務就綽綽有余,但如果需要保證該服務可用,也必須至少部署兩臺服務器,使用負載均衡技術構建一個小型的集群
-
應用服務器集群的Session管理
- 事實上,業務總是有狀態的,如交易類的電子商務網站,需要有購物車記錄用戶的購買信息等
- Web應用中將這些多次請求修改使用的上下文對象稱作為Session.單機情況下,Session可由部署在服務器上的web容器如jboss管理。在使用負載均衡的集群環境中,由于負載均衡服務器可能會將請求分發到集群中任何一臺應用服務器上,所以保證每次請求依然能夠獲得正確的Session比單機要負載的多
-
集群環境下,Session管理主要有以下幾種手段:
-
Session復制
- 應用服務器開啟web容器的session復制功能,在集群中的幾臺服務器之間同步session對象
- 只能用在集群規模比較小的情況。當集群規模較大,集群服務器之間通過大量的通信進行session復制,占用服務器和大量網絡資源,系統不堪負擔
- 所有用戶的session信息在每臺服務器上都有備份,大量用戶訪問的情況,甚至會出現服務器內存不夠session使用的情況
- 大型網站的核心應用集群就是數千臺服務器,同時在線用戶可達千萬,該方案不適用
-
Session綁定
- 利用負載均衡的源地址Hash算法實現,負載均衡服務器總是將來源統一Ip的請求分發到同一臺服務器上(也可以根據cookie信息將同一個用戶的請求總是分發到同一臺服務器上)
- 整個會話期間,用戶所有的請求都在同一臺服務器上處理,即Session綁定在某臺特定服務器上,保證Session總能在這臺服務器上獲取

- 但是這種方案不符合高可用需求,因為一旦某臺服務器宕機那么該機器上的session也就不復存在了,用戶請求切換到其他機器后因為沒有session而無法完成業務處理.雖然大部分負載均衡服務器都提供源地址負載均衡算法,但很少有網站利用這個算法進行Session管理
-
利用Cookie記錄Session
- 將session記錄在客戶端,利用瀏覽器支持的cookie記錄session

- 受Cookie大小有限,能記錄的信息有限;每次請求響應都需要傳輸cookie,影響性能;如果用戶關閉cookie,訪問就會不正常
- 但由于cookie的簡單易用,可用性高,支持應用服務器的線上伸縮,而大部分應用記錄的session信息又比較小。因為事實上許多網站或多或少地使用cookie記錄session
-
session服務器
- 利用獨立部署的Session服務器集群統一管理session
- 應用服務器每次讀寫session,都訪問session服務器

- 這種解決方案事實上是將應用服務器的狀態分離,分為無狀態的應用服務器和有狀態的session服務器,然后針對這兩種服務器的不同特性分別設計其架構
- 對于有狀態的session服務器,一種比較簡單的方法是利用分布式緩存,數據庫等,在這些產品的基礎上進行包裝,使其符合session的存儲和訪問要求
高可用的服務
- 可復用的服務模塊為業務產品提供基礎公共服務,大型網站中這些服務通常都獨立分布式部署,被具體應用遠程調用。可復用的服務和應用一樣,也是無狀態的服務,因此也可以使用類似負載均衡的失效轉移策略實現高可用的服務
-
具體實踐中的高可用服務策略
- 分級管理:運維上將服務器進行分級管理,核心應用和服務優先使用更好的硬件;同時在服務部署上也進行必要的隔離,避免故障的連鎖反應,如低優先級的服務通過啟動不同的線程或者部署在不同的虛擬機上進行隔離,而高優先級的服務則需要部署在不同的物理機上,核心服務和數據甚至需要部署在不同地域的數據中心
- 超時設置:在應用程序中設置服務調用超時時間,一旦超時,通信框架就拋出異常,應用程序根據服務調度策略,可選擇繼續重試或者將請求轉移到提供相同服務的其他機器上,避免如服務端宕機、線程死鎖引起的可能導致應用程序對服務端的調用失去響應情況,進而導致用戶請求長時間得不到響應同時還占用應用程序的資源
- 異步調用:應用對服務的調用通過消息隊列等異步方式完成;當然并非所有服務調用都可以異步調用,對于獲取用戶信息這類調用才用異步會延遲響應時間,得不償失。對于那些必須確認服務調用成功才能進行下一步操作的應用也不適合使用異步調用
-
服務降級:網站訪問高峰,服務可能因為大量的并發調用而性能下降,嚴重時會導致服務宕機。為了保證核心應用和功能的正常運行,需要對服務進行降級:
- 拒絕服務:拒絕低優先級應用的調用,減少服務調用并發數,確保核心應用正常使用;或者隨機拒絕部分請求調用,節省資源,讓另一部分請求得以成功,避免要死大家一起死
- 關閉功能:關閉部分不重要的服務或者服務內部關閉部分不重要的功能,以節約系統開銷為重要的服務和功能讓出資源
-
冪等性設計
- 服務重復調用是無法避免的,如應用調用失敗會將調用請求重新發送給其他服務器,但是這個失敗可能是個虛假的失敗,如服務已經處理成功,但是因為網絡故障應用沒有收到響應,這時應用重新提交請求就會導致服務重復調用。如果該服務是一轉賬操作,就會產生嚴重后果。而應用層不需要關心是否真的失敗,只要沒有收到成功的調用響應,就可以認為調用失敗,并重試服務調用。因為必須在服務層保證服務重復調用和調用一次產生結相同,即服務具有冪等性。
- 有些服務天生就是冪等性,如將用戶性別設置為男性,不管設置多少次,結果都一樣。但對于轉賬交易等操作,則需要通過交易編號等信息進行服務調用有效性校驗,只有有效的操作才能繼續進行
高可用的數據
- 保證數據存儲高可用的手段主要是數據備份和失效轉移機制
- 緩存的高可用,實踐中爭議很大。一種觀點因為緩存已成為數據服務的重要組成部分,緩存服務失效則可能會導致數據庫負擔過高而宕機,進而影響整個網站的可用性,因為緩存服務需要實現和數據存儲服務同樣的高可用
- 另一種觀點認為緩存服務不是數據存儲服務,緩存服務器宕機因為緩存數據丟失的導致服務器負載壓力過高應該通過其他手段解決,而不是提高緩存服務本身的高可用
- 擴大緩存服務器集群規模的一個簡單手段就是整個網站共享同一個分布式緩存集群并通過邏輯或物理分區的方式將每個應用的緩存部署在多臺服務器上,任何一臺宕機因為的緩存失效都只影響應用緩存數據的一小部分,不會對應用性能和數據庫負載造成太大影響
CAP原理
- 為了保證數據的高可用,通常會犧牲了另一個很重要的指標:數據一致性
-
高可用數據含義:
- 數據持久性:各種情況下都不會出現數據丟失的問題->數據備份一個或多個副本,存放在不同的物理存儲設備上
- 數據可訪問性:當一個數據存儲設備損壞則需要訪問切換到另一個存儲設備上,如果這個過程不能很快完成或者完成過程中需要停止用戶訪問數據,那么這段時間是不可訪問的
- 數據一致性:數據多份副本情況下,如果網絡、服務器或者軟件出現故障,會導致部分副本寫入成功,部分寫入失敗,則會造成各個副本之間數據不一致、實踐中,導致數據不一致的情形有很多種,表現形式也多種多樣
- CAP原理認為:一個提供數據服務的存儲系統無法同時滿足數據一致性、數據可用性、分區耐受性(系統具有跨網絡分區的伸縮性)

- 大型網站應用中,數據規模總是快速擴張,因為可伸縮性即分區耐受性必不可少,規模變大,機器數量也會變得龐大,這時網絡和服務器故障會頻繁出現,要想保證可用就必須保證分布式處理系統的高可用性。所以大型網站中,通常會選擇強化分布式存儲系統的可用性A和伸縮性P,而在某種程度上放棄一致性C.
- 一般說來,數據不一致通常出現在系統高并發寫操作或者集群狀態不穩如故障恢復、集群擴容
-
數據一致性
- 數據強一致
- 數據用戶一致:數據在物理存儲中的各個副本的數據可能是不一致,但終端用戶訪問通過糾錯和校驗機制,可以確定一個一致且正確的數據返回給用戶
- 數據最終一致
數據備份
- 數據冷備:定期將數據復制到某種存儲介質;缺點不能保證數據最終一致,因定期復制,備份中的數據比系統的數據舊如果系統數據丟失則從上個備份點開始后更新的數據就會永久丟失;同時也不能保證數據可永興,從冷備存儲中恢復數據需要較長的時間而這段時間無法訪問數據,系統也不可用
-
數據熱備
-
異步熱備
- 存儲服務器分為Master和Slave,應用程序正常只連接主存儲服務器,數據寫入時由master的寫操作代理模塊將數據寫入本機存儲系統后立即返回寫操作成功響應,然后通過異步線程將寫操作數據同步到slave
-
同步熱備
- 指多分數據副本的寫入操作同步完成,即應用程序收到數據服務器系統的寫成功響應時,多分數據都已經寫操縱成功.
- 具體實現的時候,為了提供性能,在用用程序客戶端并發現向多個存儲服務器同時寫入數據然后等待所有存儲服務器都返回操作成功的響應后再通知應用程序寫操作成功
- 這種情況下,存儲服務器沒有主從之分,完全對等,便于管理和維護
- 傳統的企業級關系數據庫系統幾乎都提供了數據實時同步備份的機制,而一開始就為大型網站設計的各種NoSQL數據庫如HBase更是將數據備份機制作為產品最主要的功能點
- 關系數據庫熱備機制即通常所說的master-slave同步機制,該機制不但解決了數據備份問題還該神了數據庫系統性能。實踐匯總,通常使用讀寫分離,寫操作只訪問master,讀操作只訪問slave
失效轉移
- 若數據服務器集群中任何一臺服務器宕機,那么應用程序針對這臺服務器的所有讀寫操作都需要重新路由到其他服務器,保證數據訪問不會丟失,這個過程叫做失效轉移
-
失效確認:判斷服務器宕機時系統進行失效轉移的第一步
- 心跳檢測
- 應用程序訪問失敗報告(控制中心還需要再一次進行發送心跳檢測以免錯誤判斷服務器宕機)
- 訪問轉移:確認某臺數據存儲服務器宕機后,就需要將數據讀寫訪問路由到其他服務器上(服務器是否是存儲對等,如主從結構的存儲服務器其存儲的數據完全一樣可直接切換,而不對等存儲則需要重新路由)
- 數據恢復:因為宕機所以數據存儲副本會減少,必須將副本數目恢復到系統設置的值;否則再有服務器宕機時就可能出現無法訪問轉移
高可用網站的軟件質量保證
- 網站為了保證線上系統的可用性而采取了一些與傳統軟件開發不用的質量保證手段
- 網站發布:發布過程事實上和服務器宕機效果相當,相當于一次提前預知的服務器宕機,通常使用發布腳本完成發布。發布過程每次關閉的都是集群中的一小部分并在發布完成后立即可以訪問,因此整個發布過程不影響用戶使用

- 自動化測試:目前大部分網站都采用web自動化測試技術,使用自動化測試工具或者腳本完成測試,比較流行的web自動化測試工具是ThoughtWorks開發的Selenium.大部分網站也會開發自己的自動化測試工具可以一鍵完成系統部署、測試數據生成、測試執行、測試報告生成等全部測試過程
- 預發布驗證:即使是經過嚴格的測試,軟件部署到線上服務器之后還是經常會出現各種問題,甚至根本無法啟動服務器,主要原因是測試環境和線上環境并不相同,特別是依賴的其他服務如數據庫、緩存、第三方服務如銀行網銀接口等或其他一些為如依賴的服務線上環境還沒有準備好,都有可能導致應用故障。因此網站發布時是將測試通過的代碼包發布到預發布機器上,在該機器上進行預發布驗證執行典型流程等確認系統沒有問題才正式發布。預發布服務器是一種特殊用途的服務器,它和線上正式服務器唯一不同的就是沒有配置在負載均衡服務器上,外部用戶無法訪問.網站工程師通過在自己的開發用計算機上配置hosts文件綁定域名IP關系直接用IP訪問預發布服務器.問題是預發布服務器連接的是真實的生產環境,驗證操作都是真實有效的數據,可能會引起不可預期的問題。如測試第三方支付,商品售價數千美金,為了測試工程師將金額改為1美元,但是第二天發現大量商品以1美元價格成交.另外網站應用中強調的一個處理錯誤的理念是快速失敗,即如果系統在啟動中發現問題立刻拋出異常,停止啟動讓工程師介入排查錯誤而不是啟動后執行錯誤的操作
-
代碼控制
- 網站代碼控制的核心問題是如何進行代碼管理,即能保證代碼發布版本的穩定正確同時又能保證不同團隊的開發互不影響,因為核心應用系統和公用業務模塊涉及許多團隊,需要對相同的代碼庫進行共同開發和維護。而這些團隊對同一個應用的開發維護(開發周期和發布時間點各不相同),如果控制環節出問題,則會將有問題的代碼發布上線,從而導致系統故障
-
SVN代碼控制和發布方式
- 主干開發、分支發布:代碼修改都在主干(trunk)上進行,需要發布的時候,從主干上拉一個分支(branch)發布,該分支即成為一個發布版本,如果該版本發現bug,繼續在該分支上修改發布并將修改合并(merge)回主干.
- 分支開發、主干發布:任何修改都不得在主干上直接進行,需要開發一個新功能或修復一個bug時,從主干上一個分支開發,開發完成并且測試通過則合并會主干,然后從主干上進行發布,主干上的代碼永遠是最新發布的版本
- 前者反映目前整個應用的狀態,便于管理和控制,也利于持續集成;后者各個分支獨立開發,互不干擾,可以使不同發布周期的開發在同一應用中進行
- 目前網站應用開發中主要用后者

- 因為對于前者,對于同一個應用,對于不同開發周期,不同發布時間的喜喪母,有可能A項目發布的時候,B項目只開發了一半,這時候的主干代碼是半成品,根本不能發布。而后者的話,只需要將A項目的分支合并會主干即可發布,不受B項目發布時間的影響
- 目前開源技術設計,Git正逐步取代svn地位,而Git對于分布式開發,分支開發能有更好的支持.
-
自動化發布
- 很多網站選擇周四作為發布日,這樣一周前面有三天時間可以準備發布,后面還有一天時間可以挽回錯誤。如果選擇周五發布,發現問題就必須要周末加班
- 網站火車站發布模型

- 由于火車站發布模型是基于規則驅動的流程,所以該流程可以自動化.人的干預越少,自動化程度越高,引入故障的可能性就越小
-
灰度發布
- 大型網站的主要業務服務器集群規模非常龐大,一旦發現故障,即使想要發布回滾有需要很長時間才能完成
- 大型網站會使用灰度發布模式,將集群服務器分成若干部分,每天只發布一部分服務器,觀察運行穩定沒有故障,第二天繼續發布一部分服務器,持續幾天才把整個集群全部發布完畢,期間如果發現問題則只需要回滾已發布的一部分服務器即可
- 灰度發布也長用于用戶測試,即在部分服務器上發布新版本,其余服務器保持老版本或者發布另一個版本,然后監控用戶操作行為、收集用戶提要報告、比較用戶對兩個版本的滿意度,以確定最終的發布版本。這種手段也被稱作AB測試
網站運行監控
- 不允許沒有監控的系統上線
-
監控數據采集
-
用戶行為日志收集
- 服務器端日志收集:如Apache等幾乎所有web服務器都具備日志記錄功能,可以記錄大部分用戶行為日志,開啟web服務器的日志記錄功能即可
- 客戶端瀏覽器日志收集:如利用頁面嵌入專門的javascript腳本收集用戶的真實操作,但是比較麻煩
- 因大型網站的用戶日志數據量驚人,數據存儲與計算壓力很大,目前許多網站逐步開發基于實時計算框架storm的日志統計與分析工具
-
服務器性能監控
- 收集服務器性能指標如系統Load、內存占用、磁盤IO、網絡IO等對其盡早做出故障預警
- 網站使用比較廣泛的開源性能監控工具是Ganglia,其支持大規模集群并支持以圖形的方式在瀏覽器展示實時性能曲線
-
運行數據報告
- 監控一些與具體業務場景相關的技術和業務指標,如緩存命中率、平均響應延遲時間、待處理的任務總數等
- 應用程序需要在代碼中處理運行數據采集的邏輯
-
監控管理
- 系統報警:監控指標如果某個閥值意味系統可能要出現故障->需要對相關人員報警
- 失效轉移:監控系統在發現故障的情況下主動通知應用,進行失效轉移;當然應用程序訪問失敗時也會進行失敗轉移
- 自動優雅降級:為了應付突然爆發的訪問高峰,主動關閉部分功能,釋放部分系統資源;監控系統實時監控所有服務器的運行狀況,根據監控參數判斷應用訪問負載情況
永無止境:網站的伸縮性架構
- 網站的伸縮性指不需要改變網站的軟硬件設計,僅僅通過改變部署的服務器數量就可以擴大或者縮小網站的服務處理能力
- 大型系統的漸進式的演化過程中,最重要的技術手段就是使用服務器集群,通過不斷的向集群中添加服務器來增加整個集群的處理能力
- 只要技術上能做到向集群中加入服務器的數量和集群的處理能力成線性關系,那么網站就可以以此手段不斷提升自己的規模
- 對于如電商網站的促銷活動,某個短時間內訪問量和交易規模突然爆發式增長,然后又回歸正常狀態。此時需要網站的技術架構具有極好的伸縮性-活動期間向服務器集群中加入更多服務器及向網絡服務商租借更多的網絡帶寬以滿足用戶訪問;活動結束后又將這些服務器下線以節約成本
網站架構的伸縮性設計
不同功能進行物理分離實現伸縮
- 不同的服務器部署不同的服務,提供不同的功能
-
網站發展早期-新增服務器總是從現有服務器中分離出部分功能和服務
- 縱向分離(分層后分離):將業務處理流程上的不同部分分離部署,實現系統伸縮性

- 橫向分離(業務分割后分離):將不同的業務模塊分離部署,實現系統伸縮性

單一功能通過集群實現伸縮
- 將不同功能分離部署可以實現一定程度的伸縮性,但隨著網站訪問量的逐步增加,即使分離到最小力度的獨立部署,單一的服務器也不能滿足業務規模的要求
- 必須使用服務器集群,即將相同服務部署在多臺服務器上構成一個集群整體對外提供服務
- 當一頭牛拉不動的時候,不要去尋找一頭更強壯的牛,而是用兩頭牛來拉車
- 集群伸縮性可分為應用服務器集群伸縮性和數據服務器集群伸縮性;而數據服務器集群也可以分為緩存數據服務器集群和存儲數據服務器集群
應用服務器集群的伸縮性設計
- 應用服務器設計成無狀態,即應用服務器不存儲請求上下文信息
- 利用負載均衡服務器實現請求分發:感知或者可以配置集群的服務器數量;可以及時發現集群中新上線或者下線的服務器;能向新上線的服務器分發請求,停止向已下線的服務器分發請求,即實現了應用服務器集群的伸縮性
-
實現負載均衡的基礎技術
-
HTTP重定向負載均衡
- 利用http重定向協議實現負載均衡
- http重定向服務器是一臺普通的應用服務器,其唯一的功能是根據用戶的http請求計算一臺真實的web服務器地址并將該web服務器地址寫入http重定向響應中(302)返回給有用戶瀏覽器
- 瀏覽器自動重定向請求實際的物理服務器ip,完成訪問
- 優點是比較簡單;缺點是瀏覽器需要兩次請求才能完成一次訪問,性能較差;重定向服務器自身的處理能力有可能成為瓶頸;http302響應碼重定向有可能使搜索引擎判斷為seo(Search Engine Optimization)作弊,降低搜索排名。所以實踐中并不多見

-
DNS域名解析負載均衡
- DNS服務器中配置多個A記錄,每次域名解析請求都會根據負載均衡算法計算一個不同的ip地址返回,這樣A記錄中配置多個服務器就構成了一個集群并可實現負載均衡
- 其優點是將負載均衡的工作轉交給dns,省去了網站管理維護負載服務器的麻煩;許多dns還支持基于地理位置的域名解析,可解析成距離用戶地理最近的一個服務器地址,加快用戶訪問速度
- 其缺點是dns是多級解析,每一級dns都可能緩存A記錄;當下線某臺服務器后,即使修改了dns的A記錄,要使其生效也需要較長時間,這段時間dns仍然會將域名解析到已經下線的服務器,導致用戶訪問失敗;而且dns負載均衡的控制權在域名服務商那里,網站無法對其做更多改善和更強大的管理
- 事實上,大型網站總是部分使用dns域名解析,利用域名解析作為第一級負載均衡手段,即域名解析得到的一組服務器并不是實際提供web服務的物理服務器而是同樣提供負載均衡服務的內部服務器,這組內部負載均衡服務器再進行負載均衡,將請求分發到真實的web服務器上

- 反向代理負載均衡
- IP負載均衡
- 數據鏈路層負載均衡
- 負載均衡算法
-
負載均衡算法
- Round Robin-輪詢
- Weighted Round Robin-加權輪詢
- Random-隨機
- Least Connections-最少連接
- Source Hashing-源地址散列
分布式緩存集群的伸縮性設計
- 分布式緩存服務器集群中不同服務器中緩存的數據各不相同,緩存訪問請求不可以在緩存服務器集群中的任意一臺處理,必須先找到緩存有需要數據的服務器,然后才能訪問(注:和部署相同應用的應用服務器集群不同,有狀態-數據,數據量很大,如果緩存機器數據一樣,一則失去了緩存集群的意義_就因為數據量很大才使用集群,二則集群間同步數據及其復雜)
- 必須讓新上線的緩存服務器對整個分布式緩存集群影響最小,即新加入緩存的服務器后應使整個緩存服務器集群中已經緩存的數據盡可能還被訪問到
-
Memcached分部署緩存集群的訪問模型
-
分布式緩存的一致性Hash算法
- 構造一個長度為0~2^32的整數環,即一致性hash環
- 根據節點名稱的hash值將緩存服務器節點放在這個hash環上
- 根據需要緩存數據的key值計算得到其hash值
- 在hash環上順時針查找距離這個key的hash值最近的緩存服務器節點
-
解決一致性hash算法帶來的負載不均衡問題
- 使用虛擬層,將每臺物理緩存服務器虛擬為一組虛擬緩存服務器,將虛擬緩存服務器的hash值放置在hash環上
- key在環上先找到虛擬服務器節點,再得到物理服務器的信息
數據存儲服務器集群的伸縮性設計
- 數據存儲服務器必須保證數據的可靠存儲,任何情況下都必須保證數據的可用性和正確性
-
關系數據庫集群的伸縮性設計
- 數據復制:主從-讀寫分離
- 業務分割:不同業務數據表部署在不同的數據庫集群上-分庫
-
分片:將一張表拆開分別存儲在多個數據庫重
-
NoSql數據庫的伸縮性設計
- 放棄了SQL和事務一致性保證(ACID)
- 強化高可用性和可所伸縮性
-
HBase
- 其伸縮性主要依賴其可分裂的HRegion和可伸縮性的HDFS(分布式文件系統)
- HBase啟動多個HMaster,通過Zookeeper選出一個主服務器
- 應用程序通過zookeeper獲得主HMaster的地址
- 輸入key獲得這個key所在HRegionServer地址
- 請求HRegionServer上的HRegion,獲得需要的數據
隨需應變:網站的可擴展架構
- 對現有系統影響最小的情況下,系統功能可持續擴展及提升
-
擴展性
- 指對現有系統影響最小的情況下,系統功能可持續擴展或提升的能力。表現在系統基礎設施穩定不需要經常變更、應用之間較少依賴和耦合,對需求變更可以敏捷響應。它是系統架構設計層面的開閉原則,即對擴展開放,對修改關閉、架構設計考慮未來功能擴展,當系統增加新功能時,不需要對現有系統的結構和代碼進行修改
-
伸縮性
- 指系統能夠通過增加減少自身資源規模的方式增強減少自己計算事務的能力。如果這種增減是成比例的,則為線性伸縮性。在網站架構中,通常指利用集群的方式增加服務器數量,提供系統的整體事務吞吐能力
-
利用分布式消息隊列降低系統耦合性
- 事件驅動架構
-
分布式消息隊列
- 消息生成者應用程序通過遠程訪問接口將消息推送給消息隊列服務器
- 消息隊列服務器將消息寫入本地內存隊列后立即返回給成功響應給消息生產者
- 消息隊列服務器根據消息訂閱者列表查找訂閱該消息的消息消費者應用程序,將消息隊列中的消息按照先進先出的原則將消息通過遠程通信接口發行給消息消費者程序
- 伸縮性:無狀態,將新服務器加入分布式消息隊列集群中,通知生產者服務器更改消息隊列服務器列表即可
- 可用性:如果內存隊列已滿則會將消息寫入磁盤;消息推送模塊在將內存隊列消息處理完成以后,將磁盤內容加載到內存隊列繼續處理;為了避免消息隊列服務器宕機造成消息丟失,會將消息成功發送到消息隊列的消息存儲在消息生產者服務器,等消息真正被消息消費者服務器處理后才刪除消息;在消息隊列服務器宕機后,生產者服務器會選擇分布式消息隊列服務器集群中其他的服務器發布消息
-
利用分布式服務打造可復用的業務平臺
- 將模塊獨立部署,降低系統耦合性
- 縱向拆分:將一個大應用拆分為多個小應用
- 橫向拆分:將復用的業務拆分處理,獨立部署為分布式服務
- Web Service
-
大型網站分布式服務的需求與特點:
- 負載均衡
- 失效轉移
- 高效的遠程通信
- 整合異構系統
- 對應用最少浸入
- 版本管理
- 實時監控
-
分布式服務框架設計
- Facebook#Thrift
- 阿里巴巴#Dubbo
-
可擴展的數據結構
- NoSQL#ColumnFamily-->Google#Bigtable
-
利用開放平臺建設網站生態圈
固若金湯:網站的安全架構
網站應用攻擊與防御
-
XSS(Cross Site Script)攻擊:指黑客通過篡改網頁,注入惡意html腳本,用戶瀏覽網頁時,控制用戶瀏覽器進行惡意操作的一種攻擊方式
- 消毒
- HttpOnly-進制頁面JavaScript訪問帶有httponly屬性的cookie
-
注入攻擊
-
CSRF(Cross Site Request Forgery),跨站點請求偽造-以用戶的身份偽造請求
- 表單token-隨機數
- 驗證碼
- Referer check:http請求頭中的referer域中記錄著請求來源,可通過驗證請求來源,驗證其是否合法-圖片防盜鏈
-
其他攻擊和漏洞
- Error Code:許多Web服務器默認是打開異常信息輸出的,即服務器端未處理的異常堆棧信息會直接輸出到客戶端瀏覽器,給黑客造成可乘之機.通過配置web服務器參數跳轉500(表示服務器內部錯誤)頁面到專門的錯誤頁面即可
- HTML注釋:許多開發人員會在一些服務器頁面程序中使用html注釋語法進行程序注釋,這些注釋會顯示在客戶端瀏覽器,給黑客造成攻擊便利。程序發布前需要進行代碼review或自動掃描,避免該漏洞
- 文件上傳:如果上傳一個可執行程序,則可通過該程序獲得服務端命令執行能力。防御手段是設置上傳文件白名單,只允許上傳可靠的文件類型等
- 路徑遍歷:攻擊者在請求的url中使用先對路徑,遍歷系統未開放的目錄和文件。防御方法則是將js等資源文件部署在獨立服務器、使用獨立域名,其他文件不使用靜態url訪問,動態參數不包含文件路徑信息
-
web應用防火墻
- 網站安全漏洞掃描:根據內置規則,構造具有攻擊性的url請求,模擬黑客攻擊行為,用來發現網站安全漏洞的工具
信息加密技術
-
單向散列加密-不可逆
- 因人們設置密碼具有一定的模式,可通過彩虹表(常用密碼和對應的密文關系)等手段猜測破解
- MD5,SHA
-
對稱加密
- 加密和解密使用的密鑰是同一個密鑰或者互相可推算
- DES、RC
-
非對稱加密
- 用公鑰加密的信息必須用私鑰才能解開;用私鑰加密的信息只有公鑰才能解開
- 公鑰對外界公開,私鑰只有所有者知道
- 用在信息安全傳輸、數字簽名等場合
- RSA
-
密鑰安全管理
- 將密鑰和算法放在一個獨立的服務器上
- 將加密算法放在應用系統,密鑰則放在獨立服務器中,實際存儲密鑰中,密鑰被切分成數片
信息過濾與反垃圾
電子商務風險控制
案例
淘寶
- LAMP->Java+Oracle->WebX+IBatis->JBoss替換Weblogic->Jetty替代JBoss
- WebX、AntX、Jetty
- Tair、TFS、OceanBase、TDDL
- 集群環境下分布式高可用系統的架構設計
維基百科
- GeoDNS:可將域名解析到離用戶最近的服務器
- LVS:基于Linux的開源負載均衡服務器
- Squid:基于Linux的開源反向代理服務器
- Lightttpd:開源的應用服務器
- PHP
- Memcached
- Lucene:Apache出品、Java開發的開源全文搜索引擎
- MySql
-
前端性能優化:
- 核心是反向代理服務器Squid集群,請求通過lvs負載均衡分發到squid服務器,熱點詞條被緩存,大量請求可直接返回
- Squid緩存不能命中的請求再通過lvs轉發到apache應用集群
- CDN
-
服務端性能優化
-
后端性能優化
- 使用緩存
- 熱點特別集中的數據直接緩存到應用服務器的本地內存中
- 緩存數據的內容盡量是應用服務器可以直接使用的格式
- 使用緩存服務器存儲session對象
- memcached
-
MySql
- 使用較大的服務器內存
- RAID0
- 數據庫事務一致性設置在較低水平
- Master宕機則立即切換到slave,同時關閉數據庫寫服務
海量分布式存儲系統Doris的高可用架構設計分析
- 應用程序服務器:對系統發起數據操作請求
- 數據存儲服務器:負責存儲數據、響應應用服務器的數據操作請求
- 管理中心服務器:負責集群管理,對數據存儲集群進行監控心跳檢測;集群擴容、故障恢復管理;對應用程序服務器集群地址配置信息服務等
- 數據存儲服務器根據應用的可用性級別設置數據復制份數,即每個數據實際存儲的副本數目
- 正常訪問模型:寫數據時,需要路由計算獲得兩臺不同的服務器,同時將數據寫入兩臺服務器;而讀數據時則只需要到這兩臺服務器上任意一臺服務讀取即可
-
瞬時故障的高可用解決方案:
- 多次重試
- 可能是應用服務器自己的故障,則需要請求管理中心服務器進行故障仲裁,存儲服務器進行監控心跳檢測
-
臨時故障的高可用解決方案:
- 數據有多分副本,讀數據只需要路由選擇正常服務機器即可
- 寫數據,正常服務的機器依然正常寫入,發生故障的機器需要將數據寫入到臨時存儲服務器
- 等待故障服務器恢復后再將臨時服務器中的數據遷移到該機器
-
永久故障的高可用解決方案
- 臨時故障超時或者人工確認為永久故障,系統啟動備用服務器替代原來永久失效的服務器,進入永久故障恢復
網購秒殺系統架構設計案例分析
- 秒殺系統獨立部署
- 秒殺頁面靜態化
- 租借秒殺活動網絡帶寬
- 動態生成隨機下單頁面url-下單頁面url加入由服務器端生成的隨機數作為參數,秒殺開始的時候才能得到
- 使用javascript腳本控制秒殺商品頁面購買按鈕的點亮
- javaScript服務器集群(lightttp)、定時任務服務器、秒殺商品服務器集群(apache)、下單服務器集群(jety)、訂單處理子系統、全局計數器服務器(memcached)
大型網站典型故障案例分析
-
寫日志也會引發故障
- 開發人員將log輸出的level全局配置為debug
- 應用程序自己的日志輸出配置和第三方組件日志輸出要分別配置
-
高并發訪問數據庫引發的故障
- SQL執行頻率非常高,遠超正常水平
- 這條SQL被網站首頁調用
- 首頁不應該訪問數據庫,首頁需要的數據可以從緩存服務器或者搜索服務器獲取
- 首頁最好靜態
-
高并發情況下鎖引發的故障
- 程序中某個單例對象多處使用了synchronized(this)
- 某個需要遠程調用的操作也被加了,這個操作偶爾會比被執行,但是每次執行都需要較長的時間才能完成,這段時間鎖被占用,所有的用戶線程都要等待,響應超時,這個操作執行完釋放鎖,其他線程迅速執行,超時解除
- 使用鎖操作要謹慎
-
緩存引發的故障
- 某缺乏經驗的工程師關閉了緩存服務器集群中全部的十幾臺memcached服務器,導致網站全部癱瘓-數據庫服務器Load飆升
- 當緩存不僅僅是改善性能而且成為網站架構不可或缺的一部分時,對緩存服務器的管理就需要提高到和其他服務器一樣的級別
-
應用啟動不同步引發的故障
- apache+jboss,用戶請求通過apache轉發jboss.發布時,apache和jboss同時啟動,由于jboss啟動時需要加載很多應用并初始化,花費時間較長,結果jboss還沒有完全啟動,apache就已經啟動并開始接收用戶請求,大量請求被阻塞在jboss進程中,最終導致jboss崩潰
- 網站很多場景需要后臺服務準備好,前臺應用才能啟動,否則就會導致故障
- 本例中,啟動腳本應該先啟動jboss,然后在腳本中不斷curl訪問某個特定頁面,直到收到ok,才啟動apache
-
大文件讀寫獨占磁盤引發的故障
- 圖片存儲服務器,大部分文件只有幾百k,但是有幾個文件非常大,有幾百m,讀寫這些文件一次需要幾十秒。則這段時間,磁盤基本上被這個文件操作獨占,導致其他用戶的文件操作緩慢
- 存儲的使用需要根據不同文件類型和用途進行管理
-
濫用生產環境引發的故障
- 工程師在線上生產環境進行性能壓力測試,占用了大部分帶寬
- 訪問線上生產環境要規范,不小心就會導致大事故
-
不規范的流程引發的故障
- 工程師開發,為了測試方便,特意注釋掉讀取緩存的代碼,結果開發完成后忘記把注釋去掉,直接提交到代碼庫并被發布到線上環境
- 代碼提交前使用diff命令進行代碼比較,確認沒有提交不該提交大代碼
- 加強code review,代碼在正式提交前必須被至少一個其他工程師做過code review,并且共同承擔因代碼引起的故障責任
-
不好的編程習慣引發的故障
- 程序在處理一個輸入的對象時,如果不能明確該對象是否為空,必須做空指針判斷
- 程序再調用其他方法時,輸入的對象盡量保證不是null,必要是構造空對象
架構師
-
領導藝術
- 關注人而不是產品
- 發掘人的優秀
- 共享美好藍圖
- 共同參與架構
- 學會妥協
- 成就他人
-
職場攻略
posted on 2016-07-19 14:33
landon 閱讀(1432)
評論(0) 編輯 收藏 所屬分類:
Book