第四章 瞬時響應:網站的高性能架構
4.1 網站性能測試
性能測試是性能優化的前提和基礎,也是性能優化結果的檢查和度量標準。
性能測試的指標有:響應時間、併發數、吞吐量、性能計數器。
網站性能優化的目的,除了改善用戶體驗的響應時間,還要儘量提升系統吞吐量,最大限度利用服務器資源。
4.2 Web 前端性能優化
主要手段有優化瀏覽器訪問、使用反向代理、CDN加速等。
4.2.1 瀏覽器訪問優化
- 減少http請求:合併、壓縮CSS、JS,合併圖片,使用Ajax局部刷新頁面。
- 使用瀏覽器緩存: Expires:告訴緩存器:相關副本在多長時間內是新鮮的。過了這個時間,緩存器就會向源服務器發送請求,檢查文檔是否被修改。 Cache-Control:
- > * max-age=[秒] — 執行緩存被認為是最新的最長時間。這個參數是基於請求時間的相對時間間隔,而不是絕對過期時間,[秒]是一個數字,單位是秒:從請求時間 開始到過期時間之間的秒數。
- > * s-maxage=[秒] — 類似於max-age屬性,除了他應用於共享(如:代理服務器)緩存
- > * public — 標記認證內容也可以被緩存,一般來說: 經過HTTP認證才能訪問的內容,輸出是自動不可以緩存的;
- > * no-cache — 強制每次請求直接發送給源服務器,而不經過本地緩存版本的校驗。這對於需要確認認證應用很有用(可以和public結合使用),或者嚴格要求使用最新數據 的應用(不惜犧牲使用緩存的所有好處);
- > * no-store — 強制緩存在任何情況下都不要保留任何副本
- > * must-revalidate — 告訴緩存必須遵循所有你給予副本的新鮮度的,HTTP允許緩存在某些特定情況下返回過期數據,指定了這個屬性,你高速緩存,你希望嚴格的遵循你的規則。
- > * proxy-revalidate — 和 must-revalidate類似,除了他只對緩存代理服務器起作用。 Last-Modified/If-Modified-Since:第一次請求資源時,服務器在響應頭裡設置 Last-Modified 為資源的最後修改時間,瀏覽器第二次請求資源時,在請求頭裡帶上上次響應的 Last-Modified 值,服務器檢測到資源自此值後沒有修改,則僅返回 304 響應頭。 ETag/If-None-Match:服務器發送你所請求的數據的同時,發送數據的某種 hash (在 ETag 頭信息中給出)。hash 的確定完全取決於服務器。當第二次請求相同的數據時,你需要在 If-None-Match 頭信息中包含 ETag hash,如果數據沒有改變,服務器將僅返回 304 狀態代碼。
- 服務端啟用GZip壓縮
- CSS 放在頁面最上面,JS放在頁面最下面:瀏覽器在下載完全部CSS之後才開始對整個頁面進行渲染;在加載JS後立即執行,可能會阻塞頁面,造成頁面顯示緩慢。
- 減少Cookie傳輸:Cookie包含在每次請求和響應中,太大的Cookie會影響數據傳輸;對於靜態資源,發送Cookie沒有意義,可以對靜態資源使用獨立域名。
- 對不同的靜態資源使用獨立域名:瀏覽器對同一個域同時訪問的連接數是有限制的,增加不同的域可以加快資源加載。
4.3 應用服務器性能優化
主要手段有緩存、集群、異步等。
網站性能優化第一定律:優先考慮使用緩存優化性能。
緩存主要用來存放那些讀寫比很高、很少變化的數據。
任何可以晚點做的事情都應該晚點再做。
代碼優化:
- 多線程:啟動線程數=[任務執行時間/(任務執行時間-IO等待時間)]*CPU內核數。解決線程安全的主要手段:將對象設計為無狀態對象、使用局部變量、併發訪問資源時使用鎖。
- 資源複用
- 恰當的數據結構
- 關注垃圾回收:
4.5 小結
網站性能優化的主要工作是改善高併發下情況下的網站響應速度。
網站性能對最終用戶而言是一種主觀感受,性能優化的最終目的就是改善用戶的體驗,使他們感覺網站很快。離開這個目的,追求技術上的所謂高性能,是捨本逐末,沒有多大意義。而用戶體驗的快或慢,可以通過技術手段改善,也可以通過優化交互體驗改善。
第五章 萬無一失:網站的高可用架構
5.2 高可用的網站架構
完整的高可用架構設計的主要目的是保證服務器硬件故障時服務依然可用、數據依然保存並能夠被訪問。
實現上述高可用架構的主要手段是數據和服務的冗餘備份以及失效轉移。
位於應用層和服務層的服務器為了應對高併發的訪問請求,會通過負載均衡設備將一組服務器組成一個集群共同對外提供服務。
位於數據層的服務器需要在數據寫入時進行數據同步複製,將數據寫入多臺服務器上,實現數據冗餘備份。
5.3 高可用的應用
通過負載均衡進行無狀態服務的失效轉移。
Session 管理
- Session 複製:簡單,佔用服務器內存、帶寬資源。
- Session 綁定:將同一IP或Cookie信息轉發到特定的服務器,不滿足高可用。
- 利用Cookie 記錄Session:簡單可靠性高,支持應用服務器線性伸縮;受cookie大小限制,每次請求要傳輸cookie,影響性能,如果用戶關閉cookie,訪問會不正常。
- Session 服務器:這種解決方案將應用服務器的狀態分離,分為無狀態的應用服務器和有狀態的 session 服務器;應用服務器每次讀寫 sission,都訪問 session 服務器。
5.4 高可用的服務
也是通過負載均衡和失效轉移機制失效。
- 分級管理:對服務進行分級管理,確保優先級高的服務;在部署上進行隔離,避免故障的連鎖反應。
- 超時設置:可避免請求長時間不能得到響應。
- 異步調用:應用對服務的調用通過消息隊列等異步方式完成,避免一個服務失敗導致整個應用請求失敗的情況。
- 服務降級:有兩種手段:拒絕服務和關閉關閉服務。 拒絕服務:拒絕低優先級應用的調用,減少服務調用的併發數,確保核心應用正常使用;或者隨機拒絕部分請求調用,節約資源,讓一部分請求成功,避免要死大家一起死的慘劇。 關閉服務:關閉部分不重要的服務,或者服務內部關閉部分不重要的功能,以節約系統開銷,為重要的服務和功能讓出資源。
- 冪等性設計:服務層保證重複調用和調用一次產生的結果相同,即服務具有冪等性。服務重複調用是無法避免的。
5.5 高可用的數據
保證數據高可用的手段主要是數據備份和失效轉移機制。
CAP 原理
CAP 原理認為一個提供數據服務的存儲系統無法同時滿足數據一致性(Consistency)、數據可用性(Availability)、分區耐受性(Partition Tolerence,系統具有跨網絡分區的伸縮性)。
在大型網站中,通常會選擇強化分佈式系統的可用性(A)和伸縮性(P),在某種程度上放棄一致性(C)。
數據一致性又分為:
- 數據強一致性:各個副本的數據在物理存儲中總是一致的。
- 數據用戶一致性:各個副本的數據可能是不一致的,終端用戶訪問時,通過糾錯和校驗機制,可以確定一個一致的且正確的數據返回給用戶。
- 數據最終一致:物理存儲的數據可能是不一致的,終端用戶訪問到的結果可能也是不一致的,但系統經過一段時間的自我修復和修正,數據最終會達到一致。
數據備份
數據備份分為冷備份和熱備份,熱備份又分為異步熱備份和同步熱備份。
在異步寫入方式下,存儲服務器分為主存儲服務器(Master)和從存儲服務器(Slave),應用程序通常只連接 Master,數據寫入時,由 Master 的寫代理操作模塊將數據寫入本機存儲系統後立即返回寫操作成功響應,然後通過異步線程將寫操作數據同步到 Slave。
同步方式是指多份數據副本的寫入操作同步完成,即應用程序收到數據服務系統的寫成功響應時,多份數據的都已經寫操作成功。
失效轉移
失效轉移操作由三個部分組成:失效確認、訪問轉移、數據恢復。
失效確認主要通過心跳檢測和應用程序訪問失敗報告。
5.6 高可用網站的軟件質量保證
- 網站發佈
- 自動化測試
- 預發佈驗證
- 代碼控制
- 自動化發佈
- 灰度發佈
5.7 網站運行監控
不允許沒有監控的系統上線。
監控數據採集
用戶行為日誌:
- 服務器端日誌
- 客戶端瀏覽器日誌
服務器性能監控。
運行數據報告。
監控管理
系統報警、失效轉移、自動優雅降級。
第六章 永無止境:網站的伸縮性架構
6.1 網站架構的伸縮性設計
網站的伸縮性架構可分成兩類:一類是根據功能進行物理分離實現伸縮,一類是單一功能通過集群實現伸縮。
當一頭牛拉不動車的時候,不要去找一頭更強壯的牛,而是用兩頭牛去拉車。
負載均衡的基礎技術
- HTTP 重定向負載均衡:採用 HTTP 重定向服務器,根據用戶 HTTP 請求計算一臺真實的 web 服務器地址,將該服務器地址寫入 HTTP 重定向響應中返回給用戶瀏覽器。需要兩次訪問才能完成一次請求,重定向服務器自身的處理能力有可能稱為瓶頸。
- DNS 域名解析負載均衡:在DNS 服務器中配置多個 A 記錄,每次域名解析請求都會根據負載均衡算法計算一個不同的 IP 地址返回,這樣 A 記錄中配置的多個服務器就構成一個集群,並可以實現負載均衡。DNS 的解析有延遲。
- 反向代理負載均衡:反向代理服務器需要配置雙網卡和內部外部兩套 IP 地址,工作在 HTTP 協議層,也叫應用層負載均衡。
- IP 層負載均衡:在網絡層通過修改請求目標的地址進行負責均衡。
- 數據鏈路層負載均衡:在數據鏈路層修改 mac 地址進行負載均衡。在分發過程中不修改 IP 地址,只修改目的 mac 地址,通過配置真實物理服務器集群所有機器虛擬 IP 和負載均衡服務器 IP 地址一致,從而達到不修改數據包的源地址和目的地址就可以進行數據分發的目的。也稱作直接路由(DR)。
負載均衡算法
- 輪詢(Round Robin,RR):所有請求被依次分發到每臺應用服務器上。
- 加權輪詢(Weighted Round Robin,WRR):在輪詢的基礎上,按配置的權重將請求分發到每臺服務器上。
- 隨機(Random):請求被隨機分發到各個應用服務器上。
- 最少連接(Least Connection):記錄每個應用服務器正在處理的連接數,將新到的請求分發到最少連接的服務器上。
- 源地址算列(Source Hashing):根據請求來源的 IP 地址進行分發請求,同一個 IP 總是分發到同一臺服務器上。
第七章 隨需應變:網站的可擴展性
- 擴展性(Extensibility):指對現有系統影響最小的情況下,系統功能可持續擴展或提升的能力。表現在基礎設施穩定不需要經常變更,應用之間少依賴和耦合,對需求變更可以敏捷響應。
- 伸縮性(Scalability):指系統能夠通過增加(減少)自身資源規模的方式增強(減少)自己計算處理事務的能力。這種增減是成比例的,就被稱作線性伸縮。
設計網站可擴展架構的核心思想是模塊化,並在此基礎之上,降低模塊間的耦合性,提供模塊的複用性。
分層和分割是模塊化設計的重要手段,模塊之間以消息傳遞和依賴調用的方式聚合成一個完整的系統。
模塊分佈式部署以後具體的聚合方式主要有分佈式消息隊列和分佈式服務。
大型網站分佈式服務的需求與特點:
- 服務的註冊與發現
- 服務調用
- 負載均衡
- 失效轉移
- 高效的遠程通信
- 整合異構系統
- 對應用最少入侵
- 版本管理
- 實時監控
第八章 固若金湯:網站的安全架構
閱讀更多 架構師的修煉之路 的文章