1. 程式人生 > >大型網站架構進化階段

大型網站架構進化階段

1、 最開始,由於某些想法或者愛好,於是在網際網路上搭建了一個網站,這個時候甚至有可能主機都是租借的,但由於我們先關注架構的演變歷程,因此就假設這個時候已經是託管了一臺主機,並且有一定的帶寬了。

初始階段網站架構:一臺Server滿足剛需,應用程式、資料庫、檔案等所有資源都集中在一臺Server上,典型案例:基於LAMP架構的PHP網站。


2、 經過一段時間的運營後,由於網站具備一定的特色,吸引了部分人訪問,逐漸發現系統的壓力越來越高,響應速度越來越慢,而這個時候比較明顯的是資料庫和應用互相影響,應用出問題了,資料庫也很容易出現問題,而資料庫出問題的時候,應用也容易出問題。

於是進入了第一步演變階段:將應用服務、檔案儲存、資料庫從物理上分離,變成3臺機器,這個時候技術上沒有什麼新的要求,但你發現確實起到效果了,系統又恢復到以前的響應速度了,並且支撐住了更高的流量,並且不會因為資料庫和應用搶佔資源而形成互相的影響。

應用和資料服務分離:三臺Server平天下—業務發展,單臺不再適應業務的發展,將應用和資料分離後成三臺Server(應用伺服器、檔案儲存伺服器與資料庫伺服器)。分離後三臺Server對硬體資源的需求各不相同:應用伺服器需要更快更強大的CPU,而資料庫伺服器需要更快的硬碟和更大的記憶體,檔案伺服器則需要更大的硬碟;


3、 好景不長,隨著訪問的人越來越多,你發現響應速度又開始變慢了,查詢原因,發現是訪問資料庫的操作太多,導致資料連線池競爭激烈,響應變慢,但資料庫連線又不能開太多,否則資料庫機器壓力會很高,因此,馬海祥建議你可以考慮採用快取機制來減少資料庫連線資源的競爭和對資料庫讀的壓力。

這個時候首先也許會選擇採用Squid等類似的機制來將系統中相對靜態的頁面(例如一兩天才會有更新的頁面)進行快取(當然,更好的方案是將頁面靜態化),這樣程式上可以不做修改,就能夠很好的減少對Web Server的壓力以及減少資料庫連線資源的競爭。

使用快取改善網站效能:3+X的Server模式—減少資料庫訪問壓力,提高網站的資料訪問速度。快取又可以分為:本地快取、分散式快取,本地快取訪問速度快,但資料量有限;遠端分散式快取可以叢集,因此容量不受限制;


4、 運營給力的情況下,發現隨著系統訪問量的再度增加,Web Server機器的壓力在高峰期會上升到比較高,這個時候開始考慮增加一臺Web Server,這也是為了同時解決可用性的問題,避免單臺的webserver down機的話就沒法使用了。

在做了這些考慮後,決定增加多臺Web Server,增加多臺Web Server時,會碰到一些問題,典型的有:

(1)、如何讓訪問分配到這兩臺機器上,這個時候通常會考慮的方案是Apache自帶的負載均衡方案,或者將Web服務升級為Ngnix這類同時實現HTTP和反向代理負載均衡的方案。

(2)、如何保持狀態資訊的同步,例如使用者Session等,這個時候會考慮的方案有寫入資料庫、寫入儲存、Cookie或同步Session資訊等機制等。

(3)、如何保持資料快取資訊的同步,例如之前快取的使用者資料等,這個時候通常會考慮的機制有快取同步或分散式快取。

(4)、如何讓上傳檔案這些類似的功能繼續正常,這個時候通常會考慮的機制是使用共享檔案系統或儲存等。在解決了這些問題後,終於是把Web Server增加為了多臺,系統終於是又恢復到了以往的速度。

應用伺服器叢集實現負載均衡:叢集—解決高併發、海量資料問題的常用手段,實現系統的可伸縮性。通過負載均衡排程器,可將使用者訪問分發到叢集中的某臺Server上,應用伺服器的負載壓力不再成為整個網站的瓶頸。

這一步涉及到的知識體系:負載均衡技術(包括但不限於硬體負載均衡、軟體負載均衡、負載演算法、Linux轉發協議、所選用的技術的實現細節等)、主備技術(包括但不限於ARP欺騙、Linux Heart-Beat等)、狀態資訊或快取同步技術(包括但不限於Cookie技術、UDP協議、狀態資訊廣播、所選用的快取同步技術的實現細節等)、共享檔案技術(包括但不限於NFS等)、儲存技術(包括但不限於儲存裝置等)。

 

5、 享受了一段時間的系統訪問量高速增長的幸福後,發現系統又開始變慢了,這次又是什麼狀況呢?

經過查詢,發現數據庫寫入、更新的這些操作的部分資料庫連線的資源競爭非常激烈,導致了系統變慢,這下怎麼辦呢?

此時可選的方案有資料庫叢集和分庫策略,叢集方面像有些資料庫支援的並不是很好,因此分庫會成為比較普遍的策略,分庫也就意味著要對原有程式進行修改,一通修改實現分庫後,不錯,目標達到了,系統恢復甚至速度比以前還快了。

資料庫讀寫分離:使用快取後絕大部分都可以不通過DB就能完成,但仍有一部分(快取訪問不命中、快取過期)和全部的寫操作需要訪問DB,在網站的使用者達到一定規模後,DB因為負載壓力過高成為網站的瓶頸。大部分主流DB都提供主從熱備功能,利用這一功能就可以配置兩臺DB主從關係,一臺資料更新同步到其它Server上。網站利用DB的這一功能,實現DB讀寫分離,從而改善DB負載壓力。

這一步涉及到的知識體系:這一步更多的是需要從業務上做合理的劃分,以實現分庫,具體技術細節上沒有其他的要求;但同時隨著資料量的增大和分庫的進行,在資料庫的設計、調優以及維護上需要做的更好,因此對這些方面的技術還是提出了很高的要求的。

 

6、 經過不斷的產品優化和運營,網站的訪問量也在平穩的增長當中,前端訪問的過程中,逐漸也感覺響應速度也越來越慢,檢查伺服器的資源使用狀況,伺服器一直處於比較高的負載運行當中,其中I/O吞吐量比較大,這時就需要考慮對一些靜態內容實現CDN部署,同時增加方向代理技術來快取使用者常用的資源。

反向代理和CDN加速網站響應:CDN和反向代理的基本原理都是快取,區別在於CDN部署在網路提供商的機房,而反向代理則部署在網站的中心機房。使用CDN和反向代理的目的都是儘早返回資料給使用者,一方面加快使用者訪問速度,另一方面也減輕後端伺服器的負載壓力。

 

7、 隨著資訊時代的到來,網站收集的資料呈指數倍在增長,包括結構化資料和流媒體資料等內容資料,還包括海量使用者的行為操作資料,單純的通過增加硬碟來擴充套件服務系統的儲存容量,只能解決容量大小的問題,但是在I/O訪問、資料備份、資料安全方面,還需要引入分散式檔案系統和分散式資料庫叢集來解決資料儲存和管理的問題;

分散式檔案系統和分散式資料庫系統:將單臺文件儲存的Server,擴充套件到多個檔案Server叢集,眾多的Server組成一個檔案系統網路。應用服務在讀取分散式檔案系統時,無需關心資料是儲存在哪個節點上、或者是從哪個節點從獲取的,由分散式檔案服務系統提供檔案讀寫和任務跟蹤服務;分散式資料庫叢集也是相同的原理,將原來集中式資料庫中的資料分散儲存到多個通過網路連線的資料儲存節點上,以獲取更大的儲存容量和更高的併發訪問量。

 

8、 隨著分散式檔案服務叢集和分散式資料服務叢集的部署,資料儲存和訪問的速度有了很明顯的改善,使用者體驗得到了提升,但是隨之而來的是多重資料種類的快速檢索帶來了龐大的計算量,非關係型資料的儲存容量越發龐大,急需引入NoSQL叢集解決以下問題:

1)      不需要預定義模式:不需要事先定義資料模式,預定義表結構。資料中的每條記錄都可能有不同的屬性和格式。當插入資料時,並不需要預先定義它們的模式。

2)      無共享架構:相對於將所有資料儲存的儲存區域網路中的全共享架構。NoSQL往往將資料劃分後儲存在各個本地伺服器上。因為從本地磁碟讀取資料的效能往往好於通過網路傳輸讀取資料的效能,從而提高了系統的效能。

3)      彈性可擴充套件:可以在系統執行的時候,動態增加或者刪除結點。不需要停機維護,資料可以自動遷移。

4)      分割槽:相對於將資料存放於同一個節點,NoSQL資料庫需要將資料進行分割槽,將記錄分散在多個節點上面。並且通常分割槽的同時還要做複製。這樣既提高了並行效能,又能保證沒有單點失效的問題。

5)      非同步複製:和RAID儲存系統不同的是,NoSQL中的複製,往往是基於日誌的非同步複製。這樣,資料就可以儘快地寫入一個節點,而不會被網路傳輸引起遲延。缺點是並不總是能保證一致性,這樣的方式在出現故障的時候,可能會丟失少量的資料。

6)      BASE:相對於事務嚴格的ACID特性,NoSQL資料庫保證的是BASE特性。BASE是最終一致性和軟事務。

使用NoSQL和搜尋引擎:NoSQL和搜尋引擎都是源自網際網路的技術手段,對可伸縮的分散式特性具有更好的支援。應用伺服器則通過一個統一資料訪問模組訪問各種資料,減輕應用程式管理諸多資料來源的麻煩。

9、 系統拆分和解耦是單體應用系統向分散式網站應用系統演變的關鍵一步,也是很重要的一步,拆分和解耦的好壞直接關係到未來系統的擴充套件性、可維護性和可伸縮性等,拆分工作不難理解,但是如何正確拆分、有什麼樣的方法和原則能幫助我們拆分得到一個我們理想中的系統:高可用、可擴充套件、可維護、可伸縮的分散式系統。

業務拆分與解耦:拆分過程需要遵循一個基本的原則,就是“高內聚,低耦合”,拆分的實際工作就是解耦,過程還需要遵守一些原則:

1)      業務優先:系統都會按業務功能分成多個模組,每個模組又包含許多業務相關的功能,在系統拆分時,我們就可以優先考慮按照業務邊界進行切割,切割完成後再針對每個模組進行拆解,循序漸進,逐漸迭代深入,最終完成系統的拆解。

2)      循序漸進:系統拆分過程中包含兩個非常重要的工作:拆分和測試。二者缺一不可,並且二者是並行進行的,一定要邊拆分邊測試。每一步拆分完成都要保證系統功能是完整的,保證系統的測試是完整的。

3)      兼顧技術:重構技術,拆分過程不僅僅是業務梳理的過程,也是系統進行重構的過程。通過系統的重構可以使用一些模式讓程式碼結構更清晰,具有更好的可讀性,並且方便日後的修改;分層:拆分可以讓系統分解為許多功能單一的系統,這些系統可以根據需要使用不同的技術和架構進行實現,可以讓熟悉不同技術的人做不同的事,工作更高效,產品質量也可以提高。


10、       如果需要進化到這個階段,說明這個網站已經進入超大型體量階段了,使用者可以按千萬甚至是億來計量,資料儲存可以達到PB級別了。

如果說拆分和解耦,將應用程式的不同功能單元拆分,並通過良好的介面和契約模型,可以實現分散式應用系統的架構優化,實現大型網站系統的分散式應用叢集,但是隨著應用系統的不斷開發和建設,越來越多的新功能重複疊加開發和部署,應用變成一個又大又複雜的龐大怪物,敏捷開發和部署都將是舉步維艱。

微服務架構模型:為了解決敏捷開發的困惑,提升迭代開發和維護的效率,改善部署對大型網站系統穩定性的影響,採用微服務架構是可以為帶來新的思路,一個微服務一般完成某個特定的功能,比如下單管理、客戶管理等等。每一個微服務都是微型六角形應用,都有自己的業務邏輯和介面卡。一些微服務還會發布API給其它微服務和應用客戶端使用。其它微服務完成一個Web UI,執行時,每一個例項可能是一個雲VM或者是Docker容器。


微服務架構模式有很多好處:

首先,通過分解巨大單體式應用為多個服務方法解決了複雜性問題。在功能不變的情況下,應用被分解為多個可管理的分支或服務。每個服務都有一個用RPC-或者訊息驅動API定義清楚的邊界。微服務架構模式給採用單體式編碼方式很難實現的功能提供了模組化的解決方案,由此,單個服務很容易開發、理解和維護。

其次,這種架構使得每個服務都可以有專門開發團隊來開發。開發者可以自由選擇開發技術,提供API服務。當然,許多公司試圖避免混亂,只提供某些技術選擇。然後,這種自由意味著開發者不需要被迫使用某專案開始時採用的過時技術,他們可以選擇現在的技術。甚至於,因為服務都是相對簡單,即使用現在技術重寫以前程式碼也不是很困難的事情。

再次,微服務架構模式是每個微服務獨立的部署。開發者不再需要協調其它服務部署對本服務的影響。這種改變可以加快部署速度。UI團隊可以採用AB測試,快速的部署變化。微服務架構模式使得持續化部署成為可能。

最後,微服務架構模式使得每個服務獨立擴充套件。你可以根據每個服務的規模來部署滿足需求的規模。甚至於,你可以使用更適合於服務資源需求的硬體。比如,你可以在EC2 Compute Optimized instances上部署CPU敏感的服務,而在EC2 memory-optimized instances上部署記憶體資料庫。