大型網站技術架構:核心原理與案例分析

大型網站軟件系統的特色

  1. 高併發,大流量
  2. 高可用:系統24*7小時不間斷服務
  3. 海量數據:須要存儲,管理海量數據,須要使用大量服務器
  4. 用戶分佈普遍,網絡狀況複雜:許多大型互聯網都是爲全球用戶提供服務的,用戶分佈範圍廣,各地網絡狀況千差萬別
  5. 安全環境惡劣:因爲互聯網的開放性,使得互聯網更容易受到攻擊,大型網站幾乎天天都會被黑客攻擊
  6. 需求快速變動,發佈頻繁:和傳統軟件的版本發佈頻率不一樣,互聯網產品爲快速適應市場,知足用戶需求,其產品的發佈頻率是極高的
  7. 漸進式發展:與傳統軟件產品或企業應用系統一開始就規劃好所有的功能和非功能需求不一樣,幾乎全部的大型互聯網網站都是從一個小網站開始,漸進的發展起來的。

 大型網站架構演化發展歷程

  • 初始階段的網站架構
  • 應用程序,數據庫,文件等全部的資源都在一臺服務器上

 

  • 應用服務和數據服務分離
  • 應用服務和數據服務分離
  • 應用服務器:須要處理大量的業務邏輯,所以須要更快更強大的CPU
  • 數據庫服務器:須要快速磁盤檢索和數據緩存,所以須要更快的硬盤和更大的內存
  • 文件服務器:須要存儲大量用戶上傳的文件,所以須要更大的硬盤

 

  • 使用緩存改善網站性能
  • 網站使用緩存
  • 緩存在應用服務器上的本地緩存:訪問速度更快,可是受應用服務器內存限制,其緩存數據量有限,並且會出現和應用程序爭內存的狀況。
  • 緩存在專門的分佈式緩存服務器上的遠程緩存:遠程分佈式緩存可使用集羣的方式,部署大內存的服務器做爲專門的緩存服務器,能夠在理論上作到不受內存容量限制的緩存服務。

 

  • 使用應用服務器集羣改善網站的併發處理能力
  • 應用服務器集羣部署
  • 負載均衡調度服務器:未來自用戶瀏覽器的訪問請求分發到應用服務器集羣中的任何一臺服務器上。

 

  • 數據庫讀寫分離
  • 數據庫讀寫分離
  • 主從熱備功能:經過配置兩臺數據庫主從關係,能夠將一臺數據庫服務器的數據更新同步到另外一臺服務器上。
  • 應用服務器在寫數據庫的時候,訪問主數據庫,主數據庫經過主從複製機制將數據更新同步到從數據庫,這樣當應用服務器讀數據的時候,就能夠經過從數據庫得到數據。爲了便於應用程序訪問讀寫分離後的數據庫,一般在應用服務器端使用專門的數據訪問模塊,使數據庫讀寫分離對應用透明。

 

  • 使用反向代理和CDN加速網站響應
  • 網站使用反向代理和CDN加速訪問
  • CDN和反向代理:基本原理都是緩存,區別在於CDN部署在網絡提供商的機房,使用戶在請求網站服務時,能夠從距離本身最近的網絡提供商機房獲取數據;反向代理則部署在網站的中心機房,當用戶的請求到達中心機房後,首先訪問的服務器是反向代理服務器,若是反向代理服務器中緩存着用戶請求的資源,就將其直接返回給用戶。

 

  • 使用分佈式文件系統和分佈式數據庫系統
  • 使用分佈式文件系統和分佈式數據庫系統
  • 分佈式數據庫:是網站數據庫拆分的最後手段,只有再表單數據規模很是龐大的時候才使用。不到不得已時,網站更經常使用的數據庫拆分手段是業務分庫,將不一樣的數據庫部署在不一樣的物理服務器上。

 

  • 使用NoSQL和搜索引擎
  • 使用NoSQL和搜索引擎
  • NoSQL和搜索引擎:源自互聯網的技術手段,對可伸縮的分佈式特性具備更好的支持。應用服務器則經過一個統一數據訪問模塊訪問各類數據,減輕應用程序管理諸多數據源的麻煩。

 

  • 業務拆分
  • 業務拆分
  • 業務拆分:根據產品線劃分,將一個網站拆分紅許多不一樣的應用,每一個應用獨立部署維護。應用之間能夠經過一個超連接創建關係(在首頁上的導航連接每一個都指向不一樣的應用地址),也能夠經過消息隊列進行數據分發,固然最多的仍是經過訪問同一個數據存儲系統來構成一個關聯的完整系統。

 

  • 分佈式服務
  • 分佈式服務
  • 分佈式服務:能夠將應用系統中共用的業務提取出來,獨立部署。這些可複用的業務鏈接數據庫,提供共用業務服務,而應用系統只須要管理用戶界面,經過分佈式服務調用共用業務服務完成具體業務操做。

 大型網站架構演化的價值觀

  1. 大型網站架構技術的核心價值是隨網站所需靈活應對
  2. 驅動大型網站技術發展的主要力量是網站的業務發展

網站架構設計誤區前端

  1. 一味追隨大公司的解決方案算法

  2. 爲了技術而技術spring

  3. 企圖用技術解決全部問題數據庫

 大型網站架構模式編程

  • 模式的關鍵在於模式的可重複性,問題與場景的可重複性帶來解決方案的可重複使用

大型網站架構模式

模式的關鍵在於模式的可重複性,問題與場景的可重複性帶來解決方案的可重複使用。瀏覽器

網站架構模式緩存

爲了解決大型網站面臨的高併發訪問、海量數據處理、高可靠運行等一系列問題與挑戰,大型互聯網公司在實踐中提出了許多解決方案,以實現高性能、高可用、易伸縮、可擴展、安全等各類技術架構目標。這些解決方案又被更多網站重複使用,從而逐漸造成大型網站架構模式。安全

  • 1. 分層 在實踐中,大的分層結構內部還能夠繼續分層,如:

  • (1)應用層
    • 視圖層(美工負責)
    • 業務邏輯層(工程師負責)
  • (2)服務層
    • 數據接口層(適配各類輸入和輸出的數據格式)
    • 邏輯處理層
  • 2. 分割
    • 若是說分層是將軟件在橫向方面進行切分,那麼分割就是在縱向方面對軟件進行切分。
  • 3. 分佈式
    • 對於大型網站,分層和分割的一個主要目的是爲了切分後的模塊便於分佈式部署,即將不一樣模塊部署在不一樣的服務器上,經過遠程調用協同工做。 分佈式解決網站高併發帶來問題:
    • (1).分佈式意味着服務調用必須經過網絡,這可能對性能形成比較嚴重的影響。
    • (2).服務器越多,服務器宕機的機率也就越大,一臺服務器宕機形成的服務器不可用可能會致使不少應用不可訪問,使網站可用性下降。
    • (3).數據在分佈式環境中保持數據一致性也很是困難。
    • (4)分佈式致使網站依賴錯綜複雜,開發管理維護困難。
    • 在網站應用中,經常使用的分佈式方案有如下幾種:
    • 1.分佈式應用和服務:將分層和分割後的應用和服務模塊分佈式部署。
    1. 改善網站性能和併發性
    2. 加快開發和發佈速度
    3. 減小數據庫鏈接資源消耗
    4. 使不一樣應用複用共同的服務
    5. 便於業務功能的擴展
    • 2.分佈式靜態資源:網站的靜態資源獨立分佈式部署,並採用獨立的域名,「動靜分離」。
    1. 減輕應用服務器的負載壓力
    2. 加快瀏覽器併發加載的速度
    3. 有利於網站分工合做
    • 3.分佈式數據和存儲:傳統關係數據庫和各類NoSQL幾乎都是分佈式的。
    • 4.分佈式計算:目前網站廣泛使用Hadoop及其MapReduce分佈式計算框架進行此類批處理計算,其特色是移動計算而不是移動數據,將計算程序分發到數據所在位置以加速計算和分佈式計算。
    • 5.分佈式配置:支持網站線上服務器配置實時更新。
    • 6.分佈式鎖:分佈式環境下實現併發和協同。
    • 7.分佈式文件:支持雲存儲。
  • 4. 集羣

使用分佈式已經將分層和分割後的模塊獨立部署,對於用戶訪問集中的模塊(如網站首頁),還須要將獨立部署的服務器集羣化,即多臺服務器部署相同應用構成一個集羣,經過負載均衡設備共同對外提供服務。性能優化

  • 5. 緩存

緩存就是將數據存放在距離計算最近的位置以加快處理速度。緩存是改善軟件性能的第一手段。服務器

    • (1).CDN:即內容分發網絡,部署在距離用戶最近的網絡服務商,用戶的網絡請求老是先到達網絡服務商那裏,在這裏緩存網站的一些靜態資源(較少變化的數據),就能夠以最快速度返回給用戶。
    • (2).反向代理:屬於網站前端架構的一部分,部署在網站的前端,當用戶請求到達網站的數據中心時,最早訪問到的就是反向代理服務器,這裏環迅網站的靜態資源,無需將請求繼續轉發給應用服務器就能返回給用戶。
    • (3).本地緩存:在應用服務器本地緩存着熱點數據,應用程序能夠在本機內存中直接訪問數據,而無需訪問數據庫。
    • (4)分佈式緩存:將數據緩存在一個專門的分佈式緩存集羣中,應用程序經過網絡通訊訪問緩存數據。

使用緩存兩個前提條件:

    • 數據訪問熱點不均衡,某些數據會被更頻繁的訪問,這些數據應該放在緩存中。
    • 數據在某個時間段內有效,不會很快過時,不然緩存的數據會因已經失效而產生髒讀,影響結果的正確性。
  • 6. 異步

系統解耦的手段除了分層、分割、分佈等,還有異步。業務之間的消息傳遞不是同步調用,二十將一個業務操做分紅多個階段,每一個階段之間經過共享數據的方式異步執行進行協做。

    • (1)在單一服務器內經過多線程共享內存隊列的方式實現異步。
    • (2)在分佈式系統中多個服務器集羣經過分佈式消息隊列實現異步,分佈式消息隊列可看作內存隊列的分佈式部署。

異步架構是典型的生產者消費者模式,二者不存在直接調用,只要保持數據結構不變,彼此功能實現能夠隨意變化而不互相影響,這對網站擴展新功能很是便利。除此以外,使用異步消息隊列還有以下特性:

    • (3)提升系統可用性:消費者服務器發生故障,數據會在消息隊列服務器中存儲堆積,生產者服務器能夠繼續處理業務請求,系統總體表現無端障。消費者服務器回覆正常後,繼續處理消息隊列中的數據。
    • (4)加快網站響應速度:處在業務處理前端的生產者服務器在處理完業務請求後,將數據寫入消息隊列,不須要等待消費者服務器處理就能夠返回,響應延遲減小。

消除併發訪問高峯:使用消息隊列將忽然增長的訪問請求數據放入消息隊列中,等待消費者服務器依次處理,就不會對整個網站形成太大壓力。

  • 7. 冗餘

訪問和負載很小的服務也必須部署至少兩臺服務器構成一個集羣,母的是經過冗餘實現服務器高可用。數據庫除了按期備份,存檔保存,實現冷備份外,爲了保證在線業務高可用,還須要對數據庫進行主從分離,實時同步實現熱備份。

  • 8. 自動化
    • 發佈過程自動化
    • 自動化代碼管理
    • 自動化測試
    • 自動化安全檢測
    • 自動化部署
    • 自動化監測
    • 自動化報警
    • 自動化失效轉移
    • 自動化失效恢復
    • 自動化降級
    • 自動化分配資源
  • 9. 安全
    • 經過密碼和手機校驗碼進行身份認證
    • 登陸、交易等操做須要對網絡通訊進行加密
    • 防止機器人程序攻擊網站,使用驗證碼識別
    • 對於常見的用於攻擊網站的XSS攻擊、SQL注入等相應處理
    • 對於垃圾信息、敏感信息進行過濾
    • 對交易轉帳等重要操做根據交易模式和交易信息進行風險控制

架構模式在新浪微博的應用

新浪微博的系統架構 相關連接

    • 1.基礎服務層:提供數據庫、緩存、存儲、搜索等數據服務,以及其餘一些基礎技術服務,這些服務支撐了新浪微博的海量數據和高併發訪問,是整個系統的技術基礎。
    • 2.中間層(平臺服務和應用服務層):新浪微博的核心服務是微博、關係和用戶,這些服務被分割成爲獨立的服務模塊,經過依賴調用和共享基礎數據構成呢個的新浪微博業務基礎。
    • 3.API和業務層:各類客戶端(包括Web網站)和第三方應用,經過調用API集成到新浪微博的系統中,共同組成一個生態系統。
    • 這些被分層和分割後的業務模塊與基礎技術模塊分佈式部署,每一個模塊都部署在一組獨立的服務器集羣上,經過遠程調用的方式進行依賴訪問。

小結

好的設計絕對不是模仿,不是生搬硬套某個模式,而是對問題深入理解之上的創造與創新。

大型網站核心架構要素

架構:最高層次的規劃,難以改變的命運

軟件架構:有關軟件總體結構與組件的抽象描述,用於指導大型軟件系統各個方面的設計。 軟件架構:性能、可用性、伸縮性、擴展性和安全性。

  • 性能
    • 1.瀏覽器端:經過瀏覽器緩存、使用頁面壓縮、合理佈局頁面、減小Cookie傳輸等手段改善性能。
    • 2.CDN:將網站靜態內容分發至離用戶最近的網絡服務商機房,使用戶經過最短訪問路徑獲取數據。
    • 3.反向代理服務器:緩存熱點文件,加快請求響應速度,減輕應用服務器負載壓力。
    • 4.應用服務器端:本地緩存和分佈式緩存,經過緩存在內存中的熱點數據處理用戶請求,加快請求處理過程,減輕數據庫負載壓力
    • 5.異步操做:將用戶請求發送至消息隊列等待後續任務處理,而當前請求直接返回響應給客戶。
    • 6.集羣:將多臺服務器組成一個集羣共同對外服務,提升總體處理能力,改善性能。
    • 7.代碼層面:經過使用多線程、改善內存管理等手段優化性能。
    • 8.數據庫服務器端:索引、緩存、SQL優化等性能優化手段已經比較成熟,NoSQL數據庫經過優化數據模型、存儲結構、伸縮性等手段在性能方面的優點日趨明顯。
  • 可用性

網站高可用框架設計的前提是必然會出現服務器宕機,而高可用設計的目標就是當服務器宕機的時候,服務或者應用依然可用。

網站高可用的主要手段是冗餘,應用部署在多臺服務器上同時提供訪問,數據存儲在多臺服務器上互相備份,任何一臺服務器宕機都不會影響應用的總體可用,也不會致使數據丟失。

    • 1. 對應用服務器:多臺服務器經過負載均衡設備組成一個集羣共同對外提供服務,任何一臺服務器宕機,只須要把請求切換到其餘服務器就能夠實現應用的高可用,可是一個前提條件是應用服務器上不能保存請求的會話信息。
    • 2.對存儲服務器:須要對數據進行實時備份,當服務器宕機時須要將數據訪問轉移到可用的服務器上,並進行數據恢復以保證繼續有服務器宕機的時候數據依然可用。
    • 3.對軟件質量保證:經過預發佈驗證、自動化測試、自動化測試、自動化發佈、灰度發佈等手段,減小將故障引入線上環境的可能,避免故障範圍擴大。
  • 伸縮性
    • 伸縮性是指經過不斷向集羣中加入服務器的手段來緩解不斷上升的用戶併發訪問壓力和不斷增加的數據存儲需求。 衡量架構伸縮性的主要標準就是是否可用多臺服務器構建集羣,是否容易向集羣中添加新的服務器。加入新的服務器後是否能夠提供和原來服務器無差異的服務。集羣中可容納的總的服務器數量是否有限制。
    • 1. 對於應用服務器集羣:只要服務器上不保存數據,全部的服務器都是對等的,經過使用合適的負載均衡設備就能夠向集羣中不斷加入服務器。
    • 2.對於緩存服務器集羣:加入新的服務器可能會致使緩存路由失效,進而致使集羣中大部分緩存數據都沒法訪問。雖然緩存的數據能夠經過數據庫從新加載,可是若是應用已經嚴重依賴緩存,可能會致使整個網站崩潰。須要改進緩存路由算法保證緩存數據的可訪問性。
    • 3.對於關係數據庫:雖然支持數據複製,主從熱備等機制,可是很難作到大規模集羣的可伸縮性,所以關係數據庫的集羣伸縮性方案必須在數據庫以外實現,經過路由分區等手段將部署有多個數據庫的服務器組成一個集羣。
    • 4.對於NoSQL數據庫:爲海量數據而生,所以其對伸縮性的支持一般很是好,能夠作到在較少運維參與的狀況下實現集羣規模的線性伸縮。
  • 擴展性

網站的擴展性架構直接關注網站的功能需求。

衡量網站架構擴展性好壞的主要標準就是在網站增長新的業務產品時,是否能夠實現對現有產品透明無影響,不須要任何改動或者不多改動既有業務功能就能夠上線新產品。

    • 1. 事件驅動架構:一般利用消息隊列實現,將用戶請求和其餘業務時間構形成消息發佈到消息隊列,消息的處理者做爲消費者從消息隊列中獲取消息進行處理。經過這種方式將消息產生和消息處理分離開來,能夠透明地增長新的消息生產者任務或者新的消息消費者任務。
    • 2.分佈式服務:將業務和可複用服務分離開,經過分佈式服務框架調用。新增產品能夠經過調用可複用的服務實現自身的業務邏輯,而對現有產品沒有任何影響。可複用服務升級變動的時候,也能夠經過提供多版本服務對應用實現透明升級,不須要強制應用同步變動。
    • 3.開放平臺接口:吸引第三方開發者,調用網站服務,使用網站數據開發周邊產品,擴展網站業務。
  • 安全性
    • 網站的安全架構就是保護網站不受惡意訪問和攻擊,保護網站的重要數據不被竊取。

小結

性能、可用性、伸縮性、擴展性和安全性是網站架構最核心的幾個要素。

瞬時響應:網站的高性能架構

網站性能是客觀指標,能夠具體體現到響應時間、吞吐量等技術指標,同時也是主觀的感覺,而感覺則是一種與參與者相關的微妙的東西,用戶的感覺和工程師的感覺不一樣,不一樣的用戶感覺也不一樣。

網站性能測試

不一樣視角下的網站性能

1. 用戶視角的網站性能

從用戶角度,網站性能就是用戶在瀏覽器上直觀感覺到的網站響應素的快仍是慢。

用戶感覺到的時間,包括用戶計算機和網站服務通訊的時間、網站服務器處理的時間、用戶計算機瀏覽器構造請求解析響應數據的時間。

在實踐中使用一些前端優化手段:

優化HTML式樣 利用瀏覽器端的併發和異步特性 調整瀏覽器緩存策略 使用CDN服務 反向代理

2. 開發人員視角的網站性能

開發人員關注的主要是應用程序自己及其相關子系統的性能,包括響應延遲、系統吞吐量、併發處理能力、系統穩定性等技術指標。

主要優化手段:

緩存加速數據讀取 使用集羣提升吞吐能力 使用異步消息加快請求響應及實現削峯 使用代碼優化手段改善程序性能

運維人員視角的網站性能 主要優化手段:

建設優化骨幹網 使用高性價比定製服務器 利用虛擬化技術優化資源利用

性能測試指標

1. 響應時間

響應時間是系統最重要的性能指標,直觀地反映了系統的「快慢」。

實踐中一般採用的辦法是重複請求,獲得單次請求的響應時間。

2. 併發數

指系統可以同時處理請求的數目,這個數字也反映了系統的負載特性。

網站系統用戶數 >> 網站在線用戶數 >> 網站併發用戶數

測試程序經過多線程模擬併發用戶的辦法來測試系統的併發處理能力,爲了真實模擬用戶的行爲,測試程序並非啓動多線程而後不停地發送請求,而是在兩次請求之間加入一個隨機等待時間,這個時間被稱做思考時間。

3. 吞吐量

指單位時間內系統處理的請求數量,體現系統的總體處理能力。 TPS(每秒事物數)是吞吐量的一個經常使用量化指標,還有HPS(每秒HTTP請求數、QPS(每秒查詢數)等。 在系統併發數由小逐漸增大的過程當中(伴隨着服務器系統資源消耗逐漸增大),系統吞吐量先是逐漸增長,達到一個極限後,隨着併發數的增長範兒降低,達到系統崩潰點後,系統資源耗盡,吞吐量爲零。

這個過程當中,響應時間現實小幅度上升,達到吞吐量極限後,快速上升,到達系統崩潰點後,系統失去響應。

4. 性能計數器

性能計數器是描述服務器或操做系統性能的一些數據指標,包括System Load、對象與線程數、內存使用、CPU使用、磁盤與網絡I/O等指標 System Load:即系統負載,指當前正在被CPU執行和等待被CPU執行的進程數目總和,是反映系統忙閒程度的重要指標。 性能測試方法

性能測試:以系統設計初期規劃的性能指標爲預期目標,對系統不斷施加壓力,驗證系統在資源可接受範圍內,是否能達到性能預期。

負載測試:對系統不斷地增長併發請求以增長系統壓力,直到系統的某項或多項性能指標達到安全臨界值。

壓力測試:查過安全負載的狀況下,對系統繼續施加壓力,直到系統崩潰或不能再處理任何請求,以此得到系統最大壓力承受能力。

穩定性測試:被測試系統在特定硬件、軟件、網絡環境條件下,給系統加載必定業務壓力,使系統運行一段較長時間,以此檢測系統是否穩定。在不一樣生產環境、不一樣時間點的請求壓力是不均勻的,呈波浪特性,所以爲了更好地模擬生產環境,穩定性測試也應不均勻地對系統施加壓力。

性能測試遵循如圖所示拋物線規律:

性能測試曲線

橫座標表示消耗的系統資源,縱座標表示系統處理能力(吞吐量)。

a~b段:網站的平常運行區間

c點:系統最大負載點

d點:系統崩潰點

與性能曲線相對應的是用戶訪問的等待時間(系統響應時間),如:

併發用戶訪問響應時間曲線

在平常運行區間,能夠得到最好的用戶響應時間,隨着併發用戶數的增長,響應延遲愈來愈大,直到系統崩潰,用戶失去響應。

性能測試報告

測試報告結果反映上述性能測試曲線規律,簡單示例:

性能測試結果報告

性能優化策略

1. 性能分析

檢查請求處理的各個環節的日誌,分析哪一個環節響應時間不合理、超過預期。

檢查監控數據,分析影響性能的主要因素是內存、磁盤、網絡、仍是CPU,是代碼問題仍是架構設計不合理,或者系統資源確實不足。

2. 性能優化

Web前端性能優化

應用服務器性能優化

存儲服務器性能優化

Web前端性能優化

通常說來Web前端指網站業務邏輯以前的部分,包括瀏覽器加載、網站視圖模型、圖片服務、CDN服務等,主要優化手段有優化瀏覽器訪問、使用反向代理、CDN等。

瀏覽器訪問優化

1. 減小http請求

主要手段是合併CSS、合併JavaScript、合併圖片。 將瀏覽器一次訪問須要的Javascript、CSS合併成一個文件,這樣瀏覽器只須要一次請求。

圖片也能夠合併,多張圖片合併成一張,若是每張圖片都有不一樣的超連接,可經過CSS偏移響應鼠標點擊操做構造不一樣的URL。

2. 使用瀏覽器緩存

將更新頻率比較低的、使用頻率比較高的文件緩存在瀏覽器中,能夠極好地改善性能。經過設置HTTP頭中的Cache-Control和Expires的屬性,可設定瀏覽器緩存,緩存時間能夠是數天,甚至是幾個月。

某些時候,靜態資源文件變化須要及時應用到客戶端瀏覽器,能夠經過改變文件名實現,即更新Javascript文件並非更新Javascript文件內容,而是生成一個新的Javascript文件並更新HTML文件中的引用。

使用瀏覽器緩存策略的網站在更新靜態資源時,應採用批量更新的辦法,好比須要更新10個圖標文件,不宜把10個文件一次所有更新,二十一個文件一個文件逐步更新,並有必定的間隔時間,以避免用戶瀏覽器忽然大量緩存失效,集中更新緩存,形成服務器負載驟增、網絡堵塞的狀況。

3. 啓用壓縮

在服務器端對文件進行壓縮,在瀏覽器端對文件進行解壓縮,能夠有效減小通訊傳輸的數據量。

壓縮對服務器和瀏覽器產生必定的壓力,在通訊帶寬良好,而服務器資源不足的狀況下要權衡考慮。

4. CSS放在頁面最上面、JavaScript放在頁面最下面

瀏覽器會在下載徹底部CSS以後纔對整個頁面進行渲染,所以最好的作法是將CSS放在頁面最上面,讓瀏覽器儘快下載CSS。

JavaScript則相反,瀏覽器在加載JavaScript後當即執行,有可能會阻塞整個界面,形成頁面顯示緩慢,所以JavaScript最好放在頁面最下面。

5. 減小Cookie傳輸

太大的Cookie會嚴重影響數據傳輸,儘可能減小Cookie中傳輸數據量。

對於某些靜態資源的訪問,如CSS、JavaScript等,發送Cookie沒有意義,能夠考慮靜態資源使用獨立域名訪問,避免請求靜態資源時發送Cookie,減小Cookie傳輸次數。

CDN加速

CDN(Content Distribute Network,內容分發網絡)的本質仍然是一個緩存,並且將數據緩存存在離用戶最近的地方,使用戶以最快的速度獲取數據,即網絡第一跳。

利用CDN的網站架構

CDN可以緩存的通常是靜態資源,可是這些文件訪問頻度很高。

反向代理

 

利用反向代理的網站架構

反向代理服務器具備保護網站安全的做用。

能夠經過配置緩存功能加速Web請求。

反向代理能夠實現負載均衡的功能,經過負載均衡構建的應用集羣能夠提升系統整體處理能力,進而改善網站高併發狀況下的性能。

應用服務器性能優化

應用服務器就是處理網站的服務器,網站的業務代碼都部署在這裏,是網站開發最複雜,變化最多的地方,優化手段主要有緩存、集羣、異步等。

分佈式緩存

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

1. 緩存的基本原理

緩存指將數據存儲在相對較高訪問速度的存儲媒介中,以供系統處理。一方面緩存訪問速度快,能夠減小數據訪問的時間,另外一方面若是緩存的數據是通過計算處理獲得的,那麼被緩存的數據無需重複計算便可直接使用,所以緩存還起到減小計算的做用。 緩存的本質:內存的Hash表,網站應用中,數據緩存以一對Key、Value的形式存儲在內存的Hash表中。Hash表數據讀寫的時間複雜度爲O(1)。

Hash表存儲例子

緩存主要用來存放那些讀寫比很高、變化不多的數據。

使用緩存存取數據

2. 合理使用緩存

頻繁修改的數據

若是緩存中保存的是頻繁修改的數據,就會出現數據寫入緩存後,應用還來不及讀取緩存,數據就已失效的情形,徒增系統負擔。通常來講,數據的讀寫比在2:1以上,即寫入一次緩存,在數據更新前至少讀取兩次,緩存纔有意義。

沒有熱點的訪問

緩存使用內存做爲存儲,內存資源寶貴而有限,不可能將全部的數據都緩存起來,只能將最新訪問的數據緩存起來,而將歷史數據清理出緩存。

數據不一致與髒讀

通常會對緩存的數據設置失效時間,一旦超過失效時間,就要從數據庫中從新加載。所以應用要容忍必定時間的數據不一致。在互聯網應用中,這種延遲一般是能夠接受的,可是具體應用仍需慎重對待。還有一種策略是數據更新時當即更新緩存,不過這也會帶來更多系統開銷和事務一致性問題。

緩存可用性

緩存是爲提升數據讀取性能的,緩存數據丟失或者緩存不可用不會影響到應用程序的處理,能夠從數據庫直接獲取數據。可是當緩存服務崩潰時,數據庫會有可能徹底不能承受如此大的壓力而宕機,進而致使整個網站不可用。這種狀況被叫作緩存雪崩,發生這種故障,甚至不能簡單地重啓緩存服務器和數據庫服務器來恢復網站訪問。

實踐中,有的網站經過緩存熱備等手段提升緩存可用性:當某臺緩存服務器宕機時,將緩存訪問切換到熱備服務器上。可是這種設計顯然有違緩存初衷,緩存不該該被看成可靠的數據源使用。

經過分佈式緩存服務器集羣,將緩存數據分佈到集羣多臺服務器上可在必定程度上改善緩存的可用性。當一臺緩存服務器宕機,只有部分緩存數據丟失,從新從數據庫加載這部分數據不會對數據庫產生很大影響。

緩存預熱

緩存中存放的是熱點數據,熱點數據又是緩存系統利用LRU(最近最久未用算法)對不斷訪問的數據篩選淘汰出來的,這個過程須要花費較長的時間。新啓動的緩存系統若是沒有任何數據,在重建緩存數據的過程當中,系統的性能和數據庫負載都不太好,那麼最好在緩存系統啓動時就把熱點數據加載好,這個緩存預加載手段叫作緩存預熱。對於一些元數據如城市地名列表、類目信息,能夠在啓動時加載數據庫中所有數據到緩存進行預熱。

緩存穿透

若是由於不恰當的業務、或者惡意攻擊持續高併發地請求某個不存在的數據,因爲緩存沒有保存該數據,全部的請求都會落到數據庫上,會對數據庫形成很大壓力,甚至崩潰。一個簡單的對策是將不存在的數據也緩存起來(其value值爲null)。

3. 分佈式緩存架構

分佈式緩存指緩存部署在多個服務器組成的集羣中,以集羣方式提供緩存服務,其架構方式有兩種,一種是以JBoss Cache爲表明的須要更新同步的分佈式緩存,一種是以Memcached爲表明的不相互通訊的分佈式緩存。 JBoss Cache:JBoss Cache的分佈式緩存在集羣中全部服務器中保存相同的緩存數據,當某臺服務器有緩存數據更新的時候,會通知集羣中其餘機器更新緩存數據或清除緩存數據。

須要更新同步的JBoss-Cache

JBoss Cache一般將應用程序和緩存部署在同一臺服務器上,應用程序可從本地快速獲取緩存數據,可是這種方式帶來的問題是緩存數據的數量受限於單一服務器的內存空間,並且當集羣規模較大時,緩存更新信息須要同步到集羣全部的機器,其代價驚人。於是這種方案更多見於企業應用系統中,不多在大型網站使用。

Memcached:之後講到。

4. Memcached

簡單的設計、優異的性能、互不通訊的服務器集羣、海量數據可伸縮的架構。 不互相通訊的Memcached

簡單的通訊洗衣

遠程通訊設計須要考慮兩方面的要素:

通訊協議:即選擇TCP協議仍是UDP協議,抑或HTTP協議。

通訊序列化協議:數據傳輸的兩端,必須使用彼此可識別的數據序列化方式才能使通訊得以完成,如XML、JSON等文本序列化協議,或者Google Protobuffer等二進制序列化序列化協議。

Memcached使用TCP協議(UDP也支持)通訊,其序列化協議則是一套基於文本的自定義協議,以一個命令關鍵字開頭,後面是一組命令操做數。例如讀取一個數據的命令協議是get\。

豐富的客戶端程序

Memcached通訊協議很是簡單,只要支持該協議的客戶端均可以和 Memcached服務器通訊,所以Memcached發展出很是豐富的客戶端程序,幾乎支持全部主流的網站編程語言。

高性能的網絡通訊

Memcached 服務端通訊模塊基於Libevent,一個支持事件觸發的網絡通訊程序庫。Libevent的設計和實現有許多值得改善的地方,但它在穩定的長鏈接方面的表現卻正是Memcached須要的。

高效的內存管理

Memcached使用了一個很是簡單的辦法——固定空間分配。 Memcached將內存空間分爲一組slab,每一個slab裏又包含一組chunk,同一個slab裏的每一個chunk的大小是固定的,擁有相同大小 chunk的slab被組織在一塊兒,叫做slab_class。

Memcached內存管理

存儲數據時根據數據的Size大小,尋找一個大於Size的最小chunk將數據寫入。

這種內存管理方式避免了內存碎片管理的問題,內存的分配和釋放都是以chunk爲單位的。

Memcached採用LRU算法釋放最近最久未被訪問的數據佔用的空間,釋放的chunk被標記爲未用,等待下一個合大小數據的寫入。

這種方式也會帶來內存浪費的問題。

互不通訊的服務器集羣架構

正是集羣內服務器互不通訊使得集羣能夠作到幾乎無限制的線性伸縮,這也正是目前流行的許多大數據技術的基本架構特色。

異步操做

使用消息隊列將調用異步化,可改善網站的擴展性。事實上,使用消息隊列還可改善網站系統的性能。

使用消息隊列服務器

在不使用消息隊列的狀況下,用戶的請求數據直接寫入數據庫,在高併發的狀況下,會對數據庫形成巨大的壓力,同時也使得響應延遲加重。

在使用消息隊列後,用戶請求的數據發送給消息隊列後當即返回,再由消息隊列的消費者進程(一般狀況下,該進程一般獨立部署在專門的服務器集羣上)從消息隊列中獲取數據,異步寫入數據庫。因爲消息隊列服務器處理速度遠快於數據庫(消息隊列服務器也比數據庫具備更好的伸縮性),所以用戶的響應延遲可獲得有效改善。

消息隊列具備很好的削峯做用——即經過異步處理,將短期高併發產生的事務消息存儲在消息隊列中,從而削平高峯期的併發事務。

因爲數據寫入消息隊列後當即返回給用戶,數據在後續的業務校驗、 寫數據庫等操做可能失敗, 所以在使用消息隊列進行業務異步處理後,須要適當修改業務流程進行配合,如訂單提交後,訂單數據寫入消息隊列,不能當即返回用戶訂單提交成功,須要在消息隊列的訂單消費者進程真正處理完該訂單,甚至商品出庫後,再經過電子郵件或 SMS消息通知用戶訂單成功,以避免交易糾紛。

使用集羣

在網站高併發訪問的場景下,使用負載均衡技術爲一個應用構建一個由多臺服務器組成的服務器集羣,將併發訪問請求分發到多臺服務器上處理,避免單一服務器因負載壓力過大而響應緩慢,使用戶請求具備更好的響應延遲特性。

利用負載均衡技術改善性能

代碼優化

1. 多線程

從資源利用的角度看,使用多線程的緣由主要有兩個:

IO阻塞 多CPU

啓動線程數=[任務執行時間/(任務執行時間-IO等待時間)xCPU內核數]

最佳啓動線程數和CPU內核數量呈正比,和IO阻塞時間成反比。若是任務都是CPU計算型任務,那麼線程數最多不超過CPU內核數。

解決線程安全的主要手段:

將對象設計爲無狀態對象:無狀態對象是指對象自己不存儲狀態信息(對象無成員變量,或者成員變量也是無狀態對象),這樣多線程併發訪問時候就不會出現狀態不一致。從面向對象設計角度看,無狀態對象時一種不良設計。

使用局部對象:在方法內部建立對象,這些對象會被每一個進入該方法的線程建立,除非程序有意識地將這些對象傳遞給其餘線程,不然不會出現對象被多線程併發訪問的清形。

併發訪問資源時使用鎖:多線程訪問資源的時候,經過鎖的方式使多線程併發操做轉化爲順序操做,從而避免資源被併發修改。鎖致使線程同步順序執行,可能會對系統性能產生嚴重影響。

2. 資源複用

系統運行時,要儘可能減小那些開銷很大的系統資源的建立和銷燬,好比數據庫鏈接、網絡通訊鏈接、線程、複雜對象等。 單例:Java開發經常使用的對象容器spring默認構造的對象都是單例(要注意的是 Spring 的單例是 Spring 容器管理的單例,而不是用單例模式構造的單例)。

對象池:經過複用對象實例,減小對象建立和資源消耗。對於數據庫鏈接對象,每次建立鏈接,數據庫服務端都須要建立專門的資源以應對,所以頻繁建立關閉數據庫鏈接,對數據庫服務器而言是災難性的,同時頻繁建立關閉鏈接也須要花費較長的時間。所以在實踐中,應用程序的數據庫鏈接基本都使用鏈接池(Connection Pool) 的方式。

3. 數據結構

目前比較好的字符串 Hash 散列算法有Time33算法, 即對字符串逐字符迭代乘以33,求得 Hash值,算法原型爲:

hash(i) = hash(i-1) * 33 + str[i] Time33雖然能夠較好地解決衝突,可是有可能類似字符串的HashCode也比較接近,如字符串「AA」的HashCode是2210,字符串「AB」的HashCode是2211。 這在某些應用場景是不能接受的,這種狀況下,一個可行的方案是對字符串取信息指紋,再對信息指紋求 HashCode。因爲字符串微小的變化就能夠引發信息指紋的巨大不一樣,所以能夠得到較好的隨機散列。

經過MD5計算HashCode

4. 垃圾回收

以JVM爲例,其內存主要可劃分爲堆(heap ) 和堆棧(stack)。堆棧用於存儲線程上下文信息,如方法參數、局部變量等。堆則是存儲對象的內存空間,對象的建立和釋放、垃圾回收就在這裏進行。經過對對象生命週期的觀察,發現大部分對象的生命週期都極其短暫,這部分對象產生的垃圾應該被更快地收集,以釋放內存,這就是 JVM 分代垃圾回收。

JVM分帶垃圾回收機制

存儲性能優化

機械硬盤 VS 固態硬盤

機械硬盤在數據連續訪問(要訪問的數據存儲在連續的磁盤空間上)和隨機訪問(要訪問的數據存儲在不連續的磁盤空間)時,因爲移動磁頭臂的次數相差巨大,性能表現差異也很是大。 能夠像內存同樣快速隨機訪問。並且 SSD 具備小的功耗和更少的磁盤震動與噪聲。 在網站應用中,大部分應用訪問數據都是隨機的,這種狀況下 SSD 具備更好的性能表現。

B+樹 VS LSM樹

爲了改善數據訪問特性,文件系統或數據庫系統一般會對數據排序後存儲,加快數據檢索速度,這就須要保證數據在不斷更新、插入、刪除後依然有序,傳統關係數據庫的作法是使用B+樹。

B+樹原理示意圖

B+樹是一種專門針對磁盤存儲而優化的 N 叉排序樹,以樹節點爲單位存儲在磁盤中,從根開始查找所需數據所在的節點編號和磁盤位置,將其加載到內存中而後繼續查找,直到找到所需的數據。

目前數據庫多采用兩級索引的 B+樹,樹的層次最多三層。所以可能須要 5 次磁盤訪問才能更新一條記錄(三次磁盤訪問得到數據索引及行ID而後再進行一次數據文件讀操做及一次數據文件寫操做)。

目前許多 NoSQL 產品釆用 LSM 樹做爲主要數據結構。

LSM樹原理示意圖

LSM 樹能夠看做是一個 N 階合併樹。數據寫操做(包括插入、修改、刪除)都在內存中進行,而且都會建立一個新記錄(修改會記錄新的數據值,而刪除會記錄一個刪除標誌 ),這些數據在內存中仍然仍是一棵排序樹,當數據量超過設定的內存閾值後,會將這棵排序樹和磁盤上最新的排序樹合併。當這棵排序樹的數據量也超過設定閾值後,和磁盤上下一級的排序樹合併。合併過程當中,會用最新更新的數據覆蓋舊的數據(或者記錄爲不一樣版本)。

在須要進行讀操做時,老是從內存中的排序樹幵始搜索,若是沒有找到,就從磁盤上的排序樹順序查找。

在 LSM 樹上進行一次數據更新不須要磁盤訪問,在內存便可完成,速度遠快於 B+樹。當數據訪問以寫操做爲主,而讀操做則集中在最近寫入的數據上時,使用 LSM 樹能夠極大程度地減小磁盤的訪問次數,加快訪問速度。

做爲存儲結構,B+樹不是關係數據庫所獨有的,NoSQL 數據庫也可使用 B+樹。同理,關係數據庫也可使用LSM。

RAID VS HDFS

RAID (廉價磁盤冗餘陣列)技術主要是爲了改善磁盤的訪問延遲,加強磁盤的可用性和容錯能力。目前服務器鈒別的計算機都支持插入多塊磁盤(8塊或者更多 ),經過使用RAID技術,實現數據在多塊磁盤上的併發讀寫和數據備份。

常見的RAID技術:

經常使用RAID技術原理圖

RAID0:具備極快的數據讀寫速度,可是RAID0不作數據備份,由於磁盤中只要有一塊損壞,數據完整性就被破壞,全部磁盤的數據都會損壞。

RAID1:任何一塊磁盤的損壞都不會致使數據丟失,插入一塊新磁盤就能夠經過複製數據的方式自動修復,具備極高的可靠性。

RAID10:結合RAID0和RAID1兩種方案,提升可靠性改善性能,RAID10磁盤利用率較低,有一半磁盤用來寫備份數據。

RAID3:RAID3不多在實踐中使用。

RADI5:RAID5被更多的使用,避免RAID3頻繁寫壞一塊磁盤的狀況。

RAID6:數據可靠,在出現同時損壞兩塊磁盤的狀況下,仍然能夠修復數據。

幾種RAID技術比較

RAID 技術能夠經過硬件實現,好比專用的RAID卡或者主板直接支持,也能夠經過軟件實現。RAID技術在傳統關係數據庫及文件系統中應用比較普遍,可是在大型網站比較喜歡使用的NoSQL以及分佈式文件系統中,RAID技術卻遭到冷落。 HDFS以塊(Block) 爲單位管理文件內容,一個文件被分割成若干個Block當應用程序寫文件時,每寫完一個Block,HDFS就將其自動複製到另外兩臺機器上,保證每一個Block有三個副本,即便有兩臺服務器宕機,數據依然能夠訪問,至關於實現了RAID1的數據複製功能。

當對文件進行處理計算時,經過MapReduce併發計算任務框架,能夠啓動多個計算子任務(MapReduce Task)同時讀取文件的多個Block,併發處理,至關於實現了RAID0的併發訪問功能。

HDFS架構原理圖

HDFS配合MapReduce等並行計算框架進行大數據處理時,能夠在整個集羣上併發讀寫訪問全部的磁盤,無需RAID支持。

小結

網站性能優化技術是在網站性能遇到問題時的解決方案。而網站的性能問題不少是在用戶高併發訪問時產生的,因此網站性能優化的主要工做是改善高併發用戶訪問狀況下的網站響應速度。

網站性能對最終用戶而言是一種主觀感覺,性能優化的最終目的就是改善用戶的體驗,使他們感受網站很快。

用戶體驗的快或是慢,能夠經過技術手段改善,也能夠經過優化交互體驗改善。

相關文章
相關標籤/搜索