大型網站技術架構

網站都是從小網站一步一步發展為大型網站的,而這之中的挑戰主要來自於龐大的用戶、安全環境惡劣、高併發的訪問和海量的數據,任何簡單的業務處理,一旦需要處理數以 P 計的數據和麵對數以億計的用戶時,問題就會變的很棘手。

下面我們就來說說這個演變過程:

初始階段

大型網站都是由小型網站演變而來的,網站架構也一樣

小型網站最開始沒有太多人訪問,只需要一臺服務器就綽綽有餘,就像這樣:

大型網站技術架構

應用程序、數據庫、文件等所有資源都在一臺服務器上,通常使用 Linux PHP MySQL Apache就可以完成整個項目部署,然後再買個域名,租一個廉價的服務器就可以開始我們的網站之旅了

應用服務與數據服務分離

隨著業務的發展,逐漸的一臺服務器已經不能滿足需求,這時我們可以將 應用與數據分離

分離之後我們使用到三臺服務器:應用服務器、文件服務器和數據庫服務器,如下所示:

大型網站技術架構

對於這三臺服務器要求各不相同:

應用服務器

數據庫服務器

文件服務器

應用與數據分離後,各個的職責變得更加專一,網站的性能得到進一步的提升,但隨著用戶的繼續增加,我們需要對網站架構進一步優化

使用緩存改善性能

網站的訪問一樣遵循二八定律:80% 的業務訪問集中在 20% 的數據上面

因此我們要對這一小部分的數據進行緩存來減輕數據庫的訪問壓力,以提高整個網站的數據訪問速度,改善數據庫的讀寫性能

網站的緩存可以分為兩種:緩存在應用服務器上的本地緩存和緩存在專門的分佈式緩存服務器上的遠程緩存

本地緩存

遠程分佈式緩存

如下所示:

大型網站技術架構

使用緩存後,數據訪問壓力得到了有效的緩解,但單一的應用服務器能夠處理的請求連接數有限,在訪問的高峰期,應用服務器又會成為網站性能的瓶頸

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

使用集群是網站解決高併發,海量數據問題的常用手段,當你縱向提升到一定程度後,那就該開始橫向提升了

當一臺服務器的處理能力不足時,與其換一臺更強大的服務器,不如增加一臺服務器去分擔原有的服務器壓力。對於大型網站而言,無論多麼強大的服務器,都滿足不了持續增長的業務需求,更高效的方式就是增加服務器來分擔壓力

對於網站架構而言,如果增添一臺新的服務器可以改善負載壓力,那麼就可以使用同樣的方式來應對源源不斷的業務需求,從而實現系統的可伸縮性

大型網站技術架構

通過負載均衡調度服務器,可以將用戶請求分發到應用服務器集群裡的任何一臺服務器上,如果有更多的用戶,可以增加更多的應用服務器,使應用服務器的負載壓力不再成為網站的性能問題

數據庫讀寫分離

在使用了緩存後,大多數的操作不經過數據庫訪問就能完成,但仍有一部分讀操作(緩存訪問未命中,緩存過期)和所有的寫操作需要訪問數據庫,在網站的用戶量達到一定時,數據庫的負載問題就來了

目前大多數的數據庫都支持主從熱備份,通過配置兩臺服務器的主從關係,可以將一臺數據庫服務器的數據更新同步到另一臺,網站利用這一功能,實現數據庫讀寫分離,從而進一步改善數據庫負載壓力

大型網站技術架構

應用服務器在寫操作的時候,訪問主數據庫,主數據庫通過主從複製機制把數據同步更新到從數據庫,這樣當應用服務器進行讀操作的時候,就能訪問從數據庫獲取數據

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

CDN 和 反向代理 的基本原理都是緩存

CDN

反向代理

大型網站技術架構

使用 CDN 和 反向代理 都是為了儘快返回給用戶數據,一方面加快用戶訪問速度,另一方面也減輕了後端服務器的壓力

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

隨著網站業務的繼續發展,這時候就可以像分佈式應用服務器一樣,對數據庫系統和文件系統進行分佈式管理

分佈式數據庫 是網站數據庫拆分的最後手段,一般我們可以採取業務分庫,根據不同業務的數據庫部署在不同的數據庫服務器上

大型網站技術架構

使用 NoSQL 和搜索引擎

這兩個方式都是依賴於互聯網的技術手段,應用服務器通過一個統一的數據訪問模塊來訪問各種數據,從而減輕應用程序有多個數據源的麻煩

大型網站技術架構

業務拆分

對於大型網站,我們可以分而治之,把整個網站的業務分為不同的模塊,比如大型的交易購物完整可以分為首頁、店鋪、訂單、買家等,分別交給不同的業務團隊來負責

同時我們將一個網站根據模塊劃分拆分成多個應用,每個應用進行單獨的部署和維護,應用之間通過超鏈接建立關係(指向不同的應用地址),最後通過相同的數據存儲系統來構成一個互相關聯的完整系統

大型網站技術架構

分佈式服務

隨著業務拆分,整個系統越來越大,應用的整體複雜度呈指數級增加,部署維護越來越困難,並且所有的應用服務器都要與數據庫服務連接, 在數萬臺服務器規模的情況下,這些連接的數目是服務器規模的平方,導致資源不足

這時候就要對相同的業務進行提取,獨立部署,把這些可重用的業務和連接數據庫等,提取出來作為公共業務服務,而應用系統只需要通過分佈式服務訪問公共業務服務完成業務操作

大型網站技術架構

到這裡,基本上大多數的技術問題都能得到解決,還有一些實時同步等具體業務問題也都可以通過現有的技術解決

為了使網站的能夠應對高併發訪問,海量數據處理,高可靠運行等一系列問題,我們可以選擇橫向或縱向兩個方向來入手

基本思路

首先可以對整個架構進行分層,一般可以分為 應用層 , 服務層 , 數據層 ;實踐中,大的分層結構中還可以繼續分層,比如 應用層 還可以繼續分為 視圖層 和 業務邏輯層 ,服務層也可以繼續細分為 數據接口層 邏輯處理層 等

通過分層,我們把一個龐大的系統切分為不同的部分,便於分工開發和維護;各層之間相互有一定的獨立性,在網站的開發中可以根據不同的需求進行相應的調整

邏輯上分層之後,在物理部署上也可以根據需求制定不同的策略,剛開始可以部署在同一臺物理機上,但是隨著業務的發展,必然要對不同的模塊進行分離部署

分層架構不僅僅是為了規劃軟件的邏輯結構以便於開發維護,隨著網站的發展,分層架構對網站的高併發分佈式架構來說尤為重要

進行了分層以後,接下來可以從縱向進行業務分割

根據不同的業務模塊一個項目劃分成不同的模塊交給單獨的團隊去開發部署,完成後分別部署在不同的服務器上,通過鏈接進行互聯

再根據不同情況來對不同的節點進行冗餘來保證網站的高可用性

接下來進行緩存,CDN,反向代理等等的優化,這裡以後再細說

好了,現在我們開始進入正題

架構要素

首先,對於一個高訪問量,大數據量的網站我們需要考慮什麼呢?

性能

首先就是性能了,性能是一個網站的的重要指標,除非是沒得選擇,就這一個網站,不然用戶是絕對不會忍受一個超級慢的網站

正因為性能問題無處不在,解決性能問題的方式也各種各樣,從用戶請求一個 url 開始,進行的每一個環節都可以進行優化;根據上面的分層,可以大致從三個方面進行優化,應用層優化,服務層優化,數據層優化

涉及到的知識就是 web 前端的優化,應用服務器端的優化和數據的存儲,索引,緩存等,這些在後面的內容裡會分別展開細說

但性能只是一個網站的必要條件,除此之外,因為無法預知網站可能會面臨的壓力或是攻擊,我們還要保證網站在各種情境下(高併發,高負載,持續壓力不均勻等)保持穩定的性能

可用性

對於大型網站而言,出現宕機的情況是可怕的,因為你可能有上千萬的用戶量,短短几分鐘的宕機都有可能導致網站聲譽掃地,如果是電商類的網站,更可能會導致用戶的財產損失,甚至會攤上官司,那時候損失的就不僅是金錢和用戶了

因此我們要保證能夠提供每天 24 小時的可用,但實際中服務器並不能保證每天 24 小時都能平穩的運行,可能出現硬件問題,也可能出現軟件問題,總之問題總是會有的

所以我們高可用設計的目標就是在某些服務器宕機的情況下,也能夠保證服務或應用正常運行

網站高可用的主要手段是 冗餘 ,應用部署在多臺服務器上同時提供訪問,數據存儲在多臺數據服務器之間互相進行熱備份,這樣任何一臺服務器宕機都不會影響服務或應用的整體,也不會產生數據丟失

對於應用服務器而言,多臺應用服務器通過一個負載均衡設備組成一個集群同時對外提供服務,當一臺服務器宕機後,服務切換到其他服務器上繼續執行,這樣就可以保證了網站的高可用性,前提是應用服務器不允許存儲用戶會話信息,否則將會丟失,這樣即使用戶請求轉接到其他服務器上面也無法繼續執行

對於數據存儲服務器,要提供服務器之間的實時備份,這樣當一臺服務器宕機的時候,將數據訪問切換到其他服務器上,並進行數據恢復和備份

衡量一個系統架構設計是否滿足高可用的目標,就是假設其中一臺或多臺服務器宕機以及出現各種不可預期的問題時,系統整體是否依然可用

伸縮性

面對著大量用戶的高併發訪問和海量的數據存儲,不可能只用一臺服務器就能夠滿足全部需求,存儲全部數據

通過 集群 的方式將多臺服務器組成一個整體共同提供服務,所謂 伸縮性 就是指通過不斷向集群中加入服務器的手段來應對不斷上升的用戶併發訪問壓力和不斷增長的數據存儲需求

對於應用服務器集群,只要服務器上不存儲數據,所有的服務器都是對等的,通過使用合適的負載均衡設備就可以向集群中不斷加入新的服務器

對於緩存服務器而言,加入新的服務器可能會導致緩存路由失效,從而導致大部分的緩存數據都無法訪問,需要改進緩存路由算法來保證緩存數據可訪問

關係數據庫雖然支持數據複製,主從熱備份等機制,但是很難實現大規模集群的可伸縮性

可擴展性

網站的擴展性直接關係到網站功能模塊的開發,網站快速發展,功能也不斷的增加

網站架構的可擴展性的主要目的是使其能夠快速的應對需求變化

是為了能夠在增加新業務時,儘量實現對現有產品無影響,不需要改動或是改動很少現有業務就能夠上線新產品;不同的產品業務之間的耦合度很小,一個產品或業務的改動不會對其他造成影響

大型網一定會吸引到第三方開發者,調用網站服務,開發周邊產品,擴展網站業務,這都需要網站提供開放平臺接口

安全性

最後的就是安全性了,互聯網是一個開放的平臺,任何人在任何地方都可以訪問網站,安全架構就是保護網站不受惡意的訪問和攻擊,保護數據不被竊取

性能,可用性,伸縮性,擴展性,安全性使網站架構的幾個核心要素,我們網站架構的目的主要就是為了解決這幾個問題,接下來都會分別進行介紹

高性能架構

說到高性能,在不同角色的眼中對於性能的定義也不同

  • 用戶視角: 用戶感受到的性能,就是從提交後到看到頁面的時間,不同計算機性能的差異,不同瀏覽器解析 HTML 的速度,不同網絡提供商提供的互聯網服務的速度,這些差異都會導致實際時間遠大於服務器處理請求的時間
  • 實踐中,我們可以用一些前端架構優化的手段,通過優化 HTML 樣式,利用瀏覽器異步和併發的特性,調整緩存策略,使用 CDN 服務,反向代理等,使用戶能夠儘快的看到內容,即使不對應用服務優化,也能夠很好地改善用戶體驗
  • 開發者視角: 開發者更關注的是應用服務器的性能,包括響應延遲,系統吞吐量,併發處理,系統穩定性等> 主要優化手段可以利用緩存加速數據讀取,使用集群提高吞吐量,使用異步加快請求響應,優化代碼改善程序等
  • 運維人員視角: 對於運維人員,會更關注一些基礎設施的性能和利用率,這裡不再多說

性能測試指標

主要的性能測試指標有 響應時間 併發數 吞吐量 性能計數器 等

  • 響應時間
  • 指的是從發出這個請求開始到接收到數據的時間,一般情況下這個時間都非常非常的小甚至小於測試的誤差值,所以我們可以採用重複請求的方式來獲取具體的響應時間,比如請求十萬次,記錄總時間,然後計算出單次請求的時間
  • 併發數
  • 指能夠同時處理的請求數目,對於網站而言,即併發用戶數> 有幾個詞可能會產生混淆,這裡解釋一下

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

  • 吞吐量
  • 是單位時間能能夠處理的請求數,體現的系統的整體處理能力> 衡量指標有很多,可以是 請求數/秒 頁面數/秒 訪問人數/天 處理業務數/小時 等> 常用的量化指標有 TPS(每秒事務數) HPS(每秒 HTTP 請求數) QPS(每秒查詢數) 等
  • 性能計數器
  • 描述服務器或操作系統的一些性能指標,包括系統負載(System Load),線程數,內存使用,磁盤和網絡 I/O 等,當這些值超過警告值(安全臨界值)時,就會想開發運維人員報警,及時處理異常

性能測試方法

性能測試是一個統稱,具體可以分為 性能測試 , 負載測試 , 壓力測試 , 穩定性測試

  • 性能測試
  • 以初期設計的指標為預期目標,不斷對系統施壓,看系統在預期的範圍內,能否達到預期的性能
  • 負載測試
  • 對系統不斷增加併發請求以增加系統壓力,直到系統某項或多項指標達到安全臨界值,這時繼續對系統施加壓力,系統的處理能力會有所下降
  • 壓力測試
  • 在超過安全負載的情況下,繼續施壓,直到系統崩潰或不再能夠處理任何請求,以此來計算系統的最大壓力承受能力
  • 穩定性測試
  • 在一定的壓力(不均勻施壓)下,系統能夠穩定的運行較長時間
大型網站技術架構

如上圖所示,a-b 區間內就是網站日常的運行區間,絕大多數時間都處於這一區間內;而 c 點相當於系統的最大負載點,b-c 段就是因某些原因訪問量超過了日常訪問壓力;超過了 c 點後,繼續增加壓力,這時候系統的性能就開始下降,但是資源消耗會更多,直到 d 點,系統的崩潰點,超過這個點繼續加壓的話,系統將不能處理任何請求

性能測試反映的是系統的處理能力,與其對應的是用戶的等待時間(響應時間),如下如所示:

大型網站技術架構

各點與上面的性能測試圖都相互對應,直到系統崩潰,用戶失去響應

性能優化策略

首先要定位問題產生原因,排查不同環節的日誌,分析哪個環節的響應時間與預期不相符,然後分析影響性能的原因,是代碼問題還是架構設計不合理,或者系統資源不足

然後就是性能優化,根據網站的分層架構,可以大致的分為 web 前端性能優化,應用服務器性能優化,存儲服務器性能優化三大類

具體的優化方法我們下篇再繼續

———-=======——-

根據網站的分層架構,可以大致的分為 web 前端性能優化,應用服務器性能優化,存儲服務器性能優化三大類

這次來說一下 web 前端性能優化,一般來說,web 前端就是應用服務器處理之前的部分,包括瀏覽器渲染、加載,前端視圖模型,圖片視頻資源, CDN 服務等,主要優化方法就是優化瀏覽器訪問渲染過程,使用反向代理,使用 CDN 服務等

瀏覽器訪問渲染優化

減少 http 請求數

http 協議是無狀態的應用層協議,每次 http 請求都會建立新的通信鏈路,並且在服務端,每個 http 連接都會開啟一個單獨的線程去處理請求,這都會產生額外的開銷

主要手段就是去合併壓縮 css,JavaScript,圖片文件,把需要的 css,JavaScript,圖片資源進行合併減少建立的連接請求數

同時使用 http 的 keep-alive 來進行連接的複用,以此來減少建立的 http 連接數,提高訪問性能

啟用壓縮

在服務端進行文件的壓縮,減少通信傳輸過程中的數據量

對於文本文件,壓縮率能夠達到 80% 以上,因此在服務端啟用 gzip 壓縮是一個很好的選擇,但啟用壓縮的同時也會給服務器帶來額外的開銷,所以要具體情況具體分析

css,JavaScript 代碼優化

  • css 代碼優化:
  • 儘量使用外部樣式,並且放在頁面頂部加載,一方面能夠及時渲染,另一方面能夠避免因某些樣式導致阻塞渲染
  • 壓縮合並 css 文件,儘量精簡文件,減少通信傳輸數據量和請求連接數
  • JavaScript 代碼優化:
  • 因為 JavaScript 代碼邊加載邊解析,解析的過程會阻塞瀏覽器渲染,因此把 JavaScript 代碼放在頁面底部加載
  • 同樣的壓縮合並 JavaScript 文件,儘量精簡文件,減少通信傳輸數據量和請求連接數
  • 寫高性能的 JavaScript 代碼

使用瀏覽器緩存

一般來說,對於網站裡面不經常變化的靜態資源,更新頻率比較低,因此可以把這些資源緩存在瀏覽器中,能夠很好的改善性能

通過設置 http 頭裡的 Cache-Control 和 Expires 屬性來設定瀏覽器緩存時間

另外還有 Etags 和 opcode 的緩存,根據具體情況進行選擇吧

CDN 加速

CDN 的本質也屬於緩存,內容分發網絡,把數據緩存在裡用戶近的地方,使用戶儘快的獲取數據

因為 CDN 都是部署在網絡運營商的機房,這些運營商又同時為用戶提供網絡服務,因此用戶請求的路由會優先到達 CDN 服務器,如果存在請求的資源的話,就直接返回,最短路徑返回響應,加速用戶訪問速度,同時還能夠為中心機房減輕壓力

大型網站技術架構

CDN 一般用來緩存靜態資源,css,Script 腳本,靜態頁面,圖片等,這些內容修改頻率很低但是訪問請求頻率很高,因此放在 CDN 上能夠很好的改善訪問速度

反向代理

傳統的代理服務器是當你請求不到所請求的資源時,由代理服務器幫你請求,你知道你請求的最終的服務器是誰,典型的例子就是 VPN ,通過代理服務器來請求到牆外的世界

而反向代理是當你請求一個地址時,你請求的是反向代理服務器,然後由反向代理服務器去請求其他服務器來獲取內容,而你不知道最終是從哪一臺服務器獲取到的數據

反向代理 web 服務器接收 http 請求,然後進行請求轉發,獲取到內容後返回給你,你只知道是由反向代理服務器給你的數據,而不知道數據源最終是從哪個服務器來的

大型網站技術架構

反向代理服務器具有保護作用,來自互聯網的請求都需要經過反向代理服務器,相當於在 web 服務器之間建立起了一道屏障

除了安全以外,可以在反向代理服務器上進行一些靜態資源的緩存,以此來提高訪問速度,減輕應用服務器的負載壓力

當然,有些動態資源也可以緩存在代理服務器上面,比如說熱門的詞條,帖子,博客等,這些資源的請求量可能非常非常的大,如果每次都走一遍流程的話會造成很大的壓力,同時,當這些動態內容發生改變時,會通知反向代理服務器緩存失效,代理服務器會重新緩存動態資源

除此之外,反向代理服務器還可以用來做負載均衡,通過負載均衡來構建服務器集群,以此來提高系統的總體處理能力,進而應用提高服務器處理高併發的能力

PS:使用 ajax 也是提高用戶體驗很好的方法,不過 ajax 對於 SEO 並不友好,所以需要用到 SEO 的地方還是要考慮好是否要用 ajax

好了,關於 web 前端優化就寫到這裡,下次會繼續寫應用服務器性能優化,存儲服務器性能優化

對Java微服務、分佈式、高併發、高可用、大型互聯網架構技術、面試經驗交流感興趣的。可以關注我的頭條號,我會在微頭條不定期的發放免費的資料鏈接,這些資料都是從各個技術網站蒐集、整理出來的,如果你有好的學習資料可以私聊發我,我會註明出處之後分享給大家。歡迎分享,歡迎評論,歡迎轉發!


分享到:


相關文章: