1. 程式人生 > >大型網站架構演變史

大型網站架構演變史

這篇文章是參考李智慧的《大型網站技術架構:核心原理與案例分析》和現蘑菇街CTO曽憲傑的《大型網站系統與Java中介軟體實踐》寫的一篇讀書筆記。

前言

何謂大型網站?大型網站的特點是什麼?大型網站架構發生演變的源動力是什麼?大型網站的架構演變經歷了哪些階段?在演變的某個具體階段使用到常用技術有哪些,為什麼要使用這些技術,同時這些技術又解決了什麼問題?筆者在初次接觸大型網站時思考了以上幾個問題,本著緣木求魚的方式,我打算詳細的扒一扒大型網站的演變史。如果對以上的幾個問題都理解透徹了,那麼可以說對大型網站也有一個基本的認識和理解了,但是我寫這篇文章卻不侷限於此,在文章的後面會從一箇中高階程式設計師的角度去思考,從大型網站的演變史可以得到哪些方法論和技術棧。由於筆者工作時間不長,所以我覺得思考這個問題是很有意思的。

下面將分別從以下幾個方面談談大型網站:

  • 何謂大型網站,大型網站相比非大型網站的特點有哪些?
  • 大型網站發生演變的源動力
  • 大型網站所歷經的演變階段
  • 演變階段所使用到的技術點
  • 程式設計師價值觀

大型網站的特點

從20世紀90年代第一個Web服務的出現,現在網際網路的普及,也就短短20來年的時間。網際網路極大的改變了人們的生活、學習、生活等方方面面,筆者清晰地記得在2011年剛上大學那會,用著中國移動龜速的2G怨聲載道,到現在三大運營商大力推廣並普及4G網路,再一次掀起了新一輪的網際網路革命,當我們享受著網頁秒開,看視訊再也不卡的暢快時,卻不知道背後的技術人員所付出的巨大努力。舉個例子,現在大家人手必裝的支付寶、淘寶等軟體無不從一個小網站發展起來的,然後逐漸成為一個大型網站。那麼大型網站的特點有哪些呢?

  1. 高併發,大流量

主要是指這類網站需要面對高併發、大流量訪問。騰訊QQ的最大線上人數為1.4億(2011年資料)。

  1. 高可用

因為高併發的訪問,會使得伺服器承受巨大的壓力,一旦伺服器出現過載那麼很可能直接掛掉,然後,就沒有然後了。因此,高可用就顯得尤為重要,需要保證網站7*24小時不間斷提供服務。

  1. 海量資料

主要是指需要儲存、管理海量資料。百度收錄的網頁資料有數百億,Google有將近百萬臺伺服器在提供服務。

源動力

既然大型網站是從小型網站發展起來的,那麼是什麼力量在推動著小網站逐漸向大型網站發展呢?

主要力量是業務的發展。從來沒有哪個網站生來就是大型網站,業務驅動技術變革,技術變革反作用於業務,從而使得網站可以支撐業務的快速發展。所以,從CEO(CTO)的角度看,網站的價值在於它所為使用者帶來了什麼,而不是網站是怎麼形成的。需要為使用者帶來價值是因,網站的形成是果,這個因果關係是需要認清楚的。所以,技術從來不是單純的技術(從價值的角度看),技術雖然可以解決大部分問題,但卻不一定能夠解決所有的問題。就12306網站售票的例子,如果早點使用分時段售票的做法,就沒必要投入大量的技術人員解決這個問題。業務設計也是關乎網站價值的重要方面,所以不要為了技術而技術!

演變階段

  • 階段一:單臺伺服器搞定一切
  • 階段二:應用服務與資料隔離
  • 階段三:使用快取改善效能
  • 階段四:搭建應用伺服器叢集改善併發
  • 階段五:資料庫讀寫分離減輕資料讀寫壓力
  • 階段六:使用CDN和反向代理改善網站響應
  • 階段七:使用分散式檔案系統和分散式資料庫進一步改善讀寫壓力
  • 階段八:使用NoSQL和搜尋引擎優化檢索效能
  • 階段九:業務拆分讓網站維護更簡單
  • 階段十:抽取公共服務

階段一:單臺伺服器搞定一切

由於早期使用者量不多,所以使用一臺伺服器就可以支撐業務。應用、資料、檔案都在一臺機器上完成。這個階段的典型架構就是LAMP(Linux + Apache + MySQL + PHP(Java))。搞過開發的應該都經歷過這個階段。作業系統採用Linux,使用Java或者PHP作為開發語言,使用MySQL作為資料庫,開發完後部署在Apache上。淘寶早期的架構也是這樣的。

那會阿里因為開發資源不足,所以就購買了外國的一個網上商城,把原始碼和版權都買下了(花了大概幾十萬吧),那會的淘寶的架構就是LAMP架構。

這裡寫圖片描述

階段二:應用服務與資料隔離

隨著業務量的增長,儲存的資料越來越多而造成儲存空間的不足。這時候就把應用和資料拆分,分別部署在應用伺服器、資料庫伺服器和檔案伺服器。應用伺服器由於需要處理複雜的業務邏輯,因此需要更強大的CPU,資料庫由於需要快速讀寫資料,因此需要更快的磁碟和更大的記憶體,檔案伺服器由於需要儲存大量的資料,因此需要更大容量的硬碟。需要注意的是,雖然三臺伺服器承擔了不同的角色,同時也大大改善了網站的效能,但是在整個應用中,需要的服務都是通過直連的方式完成的。直連的意思是指,當需要讀寫資料庫的資料時,是直接訪問的。雖然有壓測資料表明,在不使用任何第三方元件直接使用MySQL的併發可以達到10000多。所以,如果併發數小於這個值,直連的方式也沒有什麼問題。所以,如果併發數超過了10k,那麼資料庫的壓力就比較大了,造成的問題就是訪問時延增大,進而影響整個網站的效能。

這裡寫圖片描述

階段三:使用快取改善效能

根據“二八定律”:80%的業務訪問集中在20%的資料上,也就是說這20%的資料是熱點資料,訪問頻率相比其他資料大數倍甚至更多。所以,如果把這小部分的資料快取在記憶體中,使用者訪問的時候直接從記憶體中取,就不需要通過資料庫,從而大大降低資料庫的訪問壓力。

通常而言,快取可以分為本地快取和部署在分散式伺服器上的遠端快取。本地快取存在於應用伺服器所在的記憶體中,可能於應用資料發生爭用的情況,而遠端快取則不會存在這種情況,因為所有的資料都是熱點資料,沒有干擾。本地快取又可以分為瀏覽器快取(Cookie)、作業系統快取(如CPU的L1、L2和L3)、應用伺服器的快取(本地記憶體中)。通常可以使用ehcache作為本地快取、Redis或者Memocached作為分散式快取

這裡寫圖片描述

階段四:搭建應用伺服器叢集改善併發

截至目前的演變,應用伺服器仍然是單兵作戰,雖然以上的演變大大改善額網站的效能,但是隨著業務量的進一步上升,單臺伺服器的瓶頸就顯現出來了,因為很可能因為負載過高導致應用伺服器直接掛掉。這種情況下,更好的做法是使用增加伺服器的方式水平擴充套件,這樣就可以實現彈性伸縮,當負載過高的時候增加伺服器,當負載降下來的時候,減少伺服器。是不是很優雅?阿里在2012年提出的去“IOE”的原因之一就與這點有關。

IOE分別是指IBM、Oracle、EMC

雖然很優雅,但是應用伺服器採用叢集部署後,原來的請求過來的時候,如何知道呼叫哪臺伺服器完成請求呢?這就需要使用到負載均衡伺服器了,幹嘛的呢?就是負責將請求轉發給某臺伺服器。負載均衡又包括硬負載和軟負載。硬負載是硬體解決方案,比如F5,但是通常成本比較高,更常用的解決方案是軟負載,就是通常軟體實現負載均衡,比如LVS。

這裡寫圖片描述

階段五:資料庫讀寫分離減輕資料讀寫壓力

雖然之前使用快取將熱點資料快取起來了,但是也存在快取不命中的情況,這個時候又會直接訪問資料庫了,當快取不命中的情況增大到一定規模的時候資料庫的壓力就又是一個問題了。我們知道都資料庫進行的操作無非兩種:讀和寫。由於資料庫(比如MySQL)存在事務隔離級別和鎖的機制,可能會導致讀和寫互相阻塞,那麼如何實現資料庫的讀寫分離呢?目前的思路將資料庫進行主從拆分,所有的寫操作操作主庫,所有的讀操作操作從庫,對主庫的更新操作會通過binlog同步到從庫上,從而在從庫也可以拿到最新的資料。如此一來,讀寫不再互相阻塞,效能至少提升1倍以上。就MySQL而言,主從熱備的功能可以通過cobar、mycat之類的框架來完成。

這裡寫圖片描述

階段六:使用CDN和反向代理改善網站響應

網站的響應又一個直觀的指標(從使用者的角度)—— 訪問的快慢。這點直接關係到使用者體驗,因為如果使用者執行一個請求老半天都沒有響應,很可能就直接失去了這個使用者,然後通過口啤效應,後果很嚴重。CDN和反向代理一種提高網站響應的手段。其基本原理都是快取。CDN是部署再網路提供商所在的機房,當用戶發起一個請求的時候,優先從距離其較近的網路提供商完成請求,而反向代理則是部署再網站的中心機房,當請求到達中心機房時,會首先由反向代理伺服器完成請求,如果反向代理伺服器存在請求的資料,那麼直接返回資料給使用者。

這裡寫圖片描述

階段七:使用分散式檔案系統和分散式資料庫進一步改善讀寫壓力

當單表的資料量達到一定規模的時候,比如過千萬,即使使用資料庫索引進行優化,完成的效能提升也是有限的。因為當單表的資料量達到千萬的時候受限於執行SQL的資料庫引擎(比如MySQL的InnoDB),所以需要進行分庫分表。通常的做法時根據業務進行分庫(垂直拆分),根據單表的資料量限制做分表(水平拆分)。業務分庫需要根據具體的業務場景進行確定,相對來說比較好完成,分表就不是這樣了。因為在程式碼中寫的SQL就是一張表,現在要分表,那原來的SQL肯定有問題。這個可以通過merge引擎來完成。

這裡寫圖片描述

階段八:使用NoSQL和搜尋引擎優化檢索效能

使用NoSQL和搜尋引擎時為了解決資料查詢的需求,比如在淘寶搜尋一件商品的時候,總不能使用SQL的like進行匹配吧,效率太低!而搜尋引擎可以利用倒排索引這種資料結構很好支援資料查詢。常用的解決方案時Lucene/Solr。

這裡寫圖片描述

階段九:業務拆分讓網站維護更簡單

隨著業務場景的複雜化,將不同的業務分成不同的產品,就是把一個網站原來一個專案的情況拆分為根據不同的業務拆分為不同的專案。如果在專案中需要依賴其他專案的服務,比如在Maven工程中可以通過新增依賴的方式獲取。

這裡寫圖片描述

階段十:抽取公共服務

這點很好理解,比如在不同的業務(專案)中都需要使用使用者管理這個業務,那麼可以把這個業務抽取出來作為公共服務,需要的時候直接新增依賴即可。

這裡寫圖片描述

技術點整理

雖然大型網站演變到現在,架構已經非常複雜,但是仍然可以歸為以下的架構模型:

前端 ——> 應用層 ——> 服務層 ——> 儲存層 ——> 後臺架構

大型網站架構要素可以總結為5點:高效能、高可用、伸縮性、可擴充套件性、安全性。

高效能

主要關注以下幾個指標:響應時間(一個請求從發出請求到接收到響應資料需要的時間,是網站最重要的效能指標)、併發數(網站能夠同時處理請求的請求數)、吞吐量(單位時間內系統處理的請求數,反映了網站的整體效能)。比如TPS是指每秒的事務數、QPS是指每秒的查詢數。併發數在逐漸增大的過程中,系統的吞吐量會先逐漸增加,到達一個極限後,隨著併發數的繼續增大反而下降,直至系統資源後耗盡,吞吐量為0。這是因為併發數增大的過程實際上系統資源消耗增大的過程。而在這個過程中,響應時間會先保持小幅的上升,到達吞吐量極限後,快速上升,資源耗盡後,系統失去響應。

高可用

高可用就是在網站發生故障的時候能夠迅速處理,保證網站服務依然可用、資料依然能夠被訪問。這裡包括兩點:服務的高可用和資料的高可用。服務的高可用的通常處理策略是分級管理(核心業務使用更好的硬體資源)、超時設定(服務呼叫超時使用服務超時策略,比如繼續重試和服務呼叫轉移,由其他可用的服務提供服務)、非同步呼叫(能晚則晚)、服務降級(在效能下降或者服務宕機的時候,使用拒絕服務以及關閉服務的策略,即使是失敗也要迅速返回,而不要讓請求一直hung著)、冪等性(保證在重複呼叫的情況下返回和呼叫一次的結果相同)。資料的高可用包括資料備份和失效轉移(某臺伺服器宕機,能夠路由到其他機器繼續提供服務),在分散式環境,資料會被多個節點操作,如何保證資料的一致性是資料高可用的前提,這裡涉及的核心技術點是CAP、BASE理論。

伸縮性

在不改變現有系統架構的前提下,僅僅通過增加或者減少機器就可以改變網站的處理能力。

可擴充套件性

指的是在對現有系統影響最小的情況下,系統功能的可持續擴充套件或者提升的能力。通常表現在應用之間較少的耦合、對需求變更敏捷響應,符合開閉原則。

安全性

保護網站不受惡意訪問和攻擊,保護網站的資料不被竊取和篡改。

技術點

下面是我整理的各個要素的核心技能點,更詳細的技能圖譜將在下篇部落格中給出(思維導圖)。

高效能:分散式快取(Redis)、非同步呼叫(NIO/AIO + MQ(訊息佇列) + JVM + 程式碼優化)、HDFS

高可用:分散式Session、非同步呼叫 + 服務降級 + 冪等性保證、資料備份 + 失效轉移

伸縮性:負載均衡演算法、一致性hash、cobar叢集、Hbase

可擴充套件性:分散式訊息佇列(RabbitMQ、ActiveMQ、ZeroMQ、Kafka)、分散式服務(dubbo、gRPC)

安全性:MD5,SHA(單項雜湊加密)、DES(對稱加密)、RSA,HTTPS(非對稱加密)