前言
最近一直在拜讀兩本書:
1、李智慧老師的《大型網站技術架構 核心原理與案例分析》
2、曾憲傑老師的《大型網站系統與Java中介軟體實踐》
看了並結合自己目前的工作進行了思考,感覺獲益匪淺、受益良多,自己對大型網站的理解又有了不少的加深,下面分享一下自己的學習筆記。
學習筆記
1、大型網站架構的發展史(紅字就是每一步發展歷程的關鍵)
(1)從一個小網站發展起來,一臺伺服器,應用程式、資料庫、檔案等所有資源都在一臺伺服器上
(2)網站業務的發展,一臺伺服器逐漸不能滿足需求,因此要將應用和資料分離,應用和資料分離後使用三臺伺服器:應用伺服器、檔案伺服器和資料庫伺服器
(3)網站進一步發展,資料庫壓力太大導致訪問延遲,因此使用快取該改善網站效能(記住,使用快取是改善網站效能的第一步),網站使用的快取分為兩種:快取在應用伺服器上的本地快取和快取在專門的分散式快取伺服器上的遠端快取
(4)使用快取,資料庫訪問壓力得到有效緩解,但是在網站訪問高峰期應用伺服器還是成為了整個網站的瓶頸。這種時候要理解,不要企圖去更換更強大的伺服器,對大型網站而言,不管多麼強大的伺服器,都滿足不了網站持續增長的業務需求,因此可以通過增加伺服器的方式改善負載壓力,再通過負載均衡排程伺服器,將來自使用者瀏覽器的訪問請求分發到應用伺服器叢集中的某臺伺服器上
(5)雖然使用快取可以使大部分資料不走資料庫,但是快取沒有命中、快取過期的資料還是會走資料庫,網站達到一定規模之後,資料庫讀寫壓力還是會很大,成為網站的瓶頸。此時可以使用資料庫讀寫分離來改善資料庫負載壓力,應用伺服器寫資料走寫庫,應用伺服器讀資料走讀庫,目前大部分主流資料庫都提供主從熱備功能,通過配置兩臺資料庫主從關係,可以將一臺資料庫伺服器的資料更新同步到另一臺伺服器上
(6)隨著網站業務繼續發展,使用者規模不斷增大,由於中國複雜的網路環境,不同地區使用者訪問網站時,速度差別也極大。因此可以使用反向代理和CDN,一方面加快使用者訪問速度,另一方面減輕後端伺服器的負載壓力,因為反向代理和CDN的基本原理都是快取
(7)資料庫經過讀寫分離後,由一臺伺服器拆分為兩臺伺服器,但還是不能滿足網站業務量的需求,因此可以使用分散式資料庫,主要拆分手段是業務分庫,將不同的業務資料部署在不同的物理伺服器上
(8)大型網站為了應對日益複雜的業務場景,可以使用分而治之的手段將整個網站的業務拆分成不同的應用,每個應用獨立部署,可以通過超級鏈建立關係,也可以通過訊息佇列進行資料分發
大型網站發展到這裡,基本上大多數的技術問題都得以解決
2、高效能網站的關鍵:控制住併發的量。只要能做到這點,很多棘手的資料問題也就不是什麼問題了
3、不要企圖通過技術解決所有問題,業務的問題也可以通過業務手段去解決
比如12306建立之初,0點售票,網站一下子要承受幾千萬的訪問量,直接導致12306這個網站崩潰,各路專業人士和分專業人士眾說紛紜、出謀劃策。但這僅僅通過技術能解決問題嗎?所以,針對這個需求,12306不僅要改善它的技術架構,也要調整它的業務架構,不要0點售票,在售票方式上引入排隊機制、整點售票改為分時段售票,併發量控制住了,整個網站的效能就改善了
4、計算機軟體發展的 一個重要目標和驅動力是降低軟體的耦合性,事物之間關係越少,就越少彼此影響,越可以獨立發展
5、非同步架構是典型的生產者消費者模式
6、使用非同步佇列有幾個好處
(1)提高系統的可用性
(2)加快網站的訪問速度
(3)消除併發訪問高峰
7、網站伸縮性就是指通過不斷向叢集中加入伺服器的手段來緩解不斷上升的使用者併發訪問壓力和不斷增長的資料儲存需求
8、衡量架構伸縮性的指標
(1)是否可用多臺伺服器架構叢集
(2)是否容易向伺服器中新增新的伺服器
(3)加入的伺服器是否可以提供和原伺服器無差別的服務
(4)叢集中容納的總伺服器是否有限制
9、反應系統忙閒的重要指標Load
System Load也稱為Load,即系統負載,指當前正在被CPU執行和等待被CPU執行的執行緒數之和,,是反映系統忙閒程度的重要指標。多核CPU下,完美情況應該是所有CPU都在用,沒有執行緒等待處理。Load值低於CPU數目,表示CPU有空閒,資源存在浪費;Load值高於CPU數目,表示程式在等待CPU排程,資源存在不足
10、瀏覽器訪問優化手段
(1)減少http請求,合併CSS、JS、圖片,不要發起多次http請求去拿這些資料
(2)使用瀏覽器快取,儲存靜態資源,Cache-Control、Expires、Pragma、Last_Modified都是和快取的HTTP HEADER
(3)啟用壓縮,有效減低通訊傳輸的資料量
(4)CSS放在上面、JS放在下面,因為JS下載會立即執行,可能阻塞頁面載入速度
(5)減少Cookie傳輸
11、快取使用的幾點細節
(1)頻繁修改的資料不要寫快取,一般讀寫比例至少2:1以上才會做快取,即一次寫入至少有兩次以上的讀取,像新浪微博這種,熱門微博,一次寫入可能會被讀取數百萬次,那是大大地合算
(2)如果訪問沒有熱點,大部分資料的訪問沒有集中在小部分資料上,那麼做快取就沒有意義,因為快取有失效機制,大部分資料還沒有被再次訪問就被擠出快取了
(3)容忍一定時間的資料不一致,除非資料更新時立刻通知快取,不過這也會帶來開銷與事物一致性的問題
(4)使用分散式快取叢集以提高快取可用性
(5)新啟動的快取沒有任何資料,在重建快取的過程中,系統效能與資料庫負載都不太好,因此要根據專案、根據業務,將一部分資料在啟動時就載入好,這就是快取預熱
(6)對快取做無效引數並設定失效時間,避免不恰當的業務或惡意攻擊頻繁呼叫介面查詢資料庫,一旦某一個Key值資料庫裡面查不到資料就進入無效快取,一段時間內再次訪問這個Key值無資料返回
12、訊息佇列具有很好的削峰作用(前面提過),不過注意需要適當修改業務流程進行配合
通過非同步處理,將短時間高併發產生的事物訊息儲存在訊息佇列中,從而可以削平高峰期的併發事物。不過要注意點,由於資料寫入訊息佇列後立即返回給使用者,資料在後續的業務校驗、寫資料庫等操作可能失敗,因此在使用訊息佇列進行業務非同步處理後,,需要適當修改業務流程進行配合,如訂單提交之後,訂單資料寫入訊息佇列,不能立即返回給使用者訂單提交成功,需要在訊息佇列的訂單消費者程式真正處理完該訂單的,甚至商品出庫後,再通過電子郵件或者SMS訊息通知使用者訂單成功,避免交易糾紛
13、CDN和反向代理的基本原理都是快取,區別在於CDN部署在網路提供商的機房,使使用者在請求網站服務時,可以從距離自己最近的網路提供商機房獲取資料;反向代理則部署在網站的中心機房,當使用者請求到達中心機房時,首先訪問的是反向代理伺服器,如果反向代理伺服器中快取著使用者請求的資源,就將其直接返回給使用者。使用CDN和反向代理的目的是一樣的:
(1)儘早返回速度給使用者,加快使用者訪問網站的速度
(2)減輕後端伺服器的負載壓力
14、應用伺服器叢集的Session管理
單機環境下,Session可由部署在伺服器上的Web容器管理,在使用負載均衡的叢集環境中,由於負載均衡伺服器可能會將請求分發到叢集任何一臺應用伺服器上,所以保證每次請求依然能夠獲得正確的Session比單機時要複雜得多。叢集環境下,Session管理有以下手段:
1、Session複製
在叢集中的幾臺伺服器之間同步Session物件,使得每臺伺服器上都儲存著所有使用者的Session資訊,這樣任何一臺機器當機都不會導致Session資料的丟失,而伺服器使用Session時,也只需要從本機獲取即可。
這種方案雖然簡單,從本機讀取Session資訊也很快,但只能使用在叢集規模比較小的情況下。當叢集規模較大時,叢集伺服器之間需要大量的通訊進行Session複製,佔用伺服器和網路的大量資源,系統不堪負擔。而且由於所有使用者的Session在每臺伺服器都有備份,在大量使用者訪問的情況下,甚至會出現伺服器記憶體不夠Session使用的情況。
大型網站的核心應用叢集就是數千臺伺服器,同時線上使用者達到數千萬,並不適用這種方案。
2、Session繫結
Session繫結可以利用負載均衡的原地址Hash演算法,負載均衡伺服器總是將來源於同一IP的請求分發到同一臺伺服器。這樣在整個會話期間,使用者所有請求都在同一臺伺服器上處理,即Session繫結在某臺特定伺服器上,保證Session總能在這臺伺服器上獲取,這種方法又被稱為會話粘滯。
但是Session繫結的方案不符合對系統高可用的需求,因為一旦某臺伺服器當機,那麼該機器上的Session也就不復存在了,使用者請求切換到其他機器後因為沒有Session而無法完成業務處理。因此雖然大部分負載均衡伺服器都提供原地址負載均衡演算法,但很少有網站利用這個演算法進行Session管理
3、利用Cookie記錄Session
早期的企業應用使用C/S架構,一種管理Session的方式是將Session記錄在客戶端,每次請求伺服器的時候,將Session放在請求中傳送給伺服器,伺服器處理完請求後再將修改過的Session響應給客戶端。網站沒有客戶端,但是可以利用瀏覽器支援的Cookie記錄Session。
利用Cookie記錄Session也有一些缺點:
(1)受到Cookie大小限制,能記錄的資訊有限
(2)每次請求和響應都攜帶Cookie,影響效能
(3)如果使用者關閉Cookie,訪問就會不正常
不過因為Cookie簡單易用且可用性高,支援應用伺服器的線性伸縮,而大部分應用需要記錄的Session資訊有比較小,因此事實上,許多網站或多 或少都會使用Cookie記錄Session
4、Session伺服器
利用獨立部署的Session伺服器(叢集)統一管理Session,應用伺服器每次讀寫Session時,都訪問Session伺服器。
這種解決方案事實上是將應用伺服器的狀態分離,分為無狀態的應用伺服器和有狀態的Session伺服器,然後針對這兩種伺服器的不同特性分別設計其架構。
對於有狀態的Session伺服器,一種比較簡單的方法是利用分散式快取、資料庫等,在這些產品的基礎上進行包裝,使其符合Session的儲存和訪問要求;如果業務場景對Session管理有比較高的要求,那麼就要利用Session服務整合單點登入(SSO)、使用者服務等功能,則需要開發專門的Session服務管理平臺。