Web開發如何應對大流量是必須考慮的問題,例如當前的12306網站、淘寶的秒殺系統等都是Web系統會遇到的典型問題。尤爲是一些突發流量更是會考驗咱們系統抗壓的能力,因此在設計系統時要考慮不少因素,例如網絡結構,網卡瓶頸,系統依賴,緩存,數據一致性等。因此接下來將以淘寶爲例,講述如何大瀏覽量的系統的靜態化架構。前端
什麼是大瀏覽量系統?以java系統爲例,正常的用戶請求要支撐20w/s的QPS(每秒查詢率)。根據Alexa全球排名,淘寶目前排名第13位,日均PV(Page View)約有25億,日均獨立IP訪問約有1.5億,其中item.taobao.com域名對應的Detail系統約佔總PV的25%。能夠說Detail系統是目前淘寶中單系統訪問量最高的系統,當前每秒約有20KB的請求到達淘寶的服務器後端。java
下面介紹這個大瀏覽量系統的基本狀況:web
頁面大小45KB,壓縮後15KB,峯值帶寬2Gbps,服務端頁面平均RT約15ms.數據庫
靜態化改造以前,淘寶的前臺系統結構:json
圖1.前臺系統基本結構後端
前面的Http請求通過負載均衡設備分配到某個域名對應的應用集羣,通過Nginx代理到JBoss或者Tomcat容器,由他們負責具體處理用戶的請求。目前這些大瀏覽量的系統大部分須要讀取的數據都已經直接走K/V緩存了,不會直接從DB中獲取數據。還有一部分應用邏輯會走遠程的系統調用。淘寶有一套高性能的分佈式服務架構(HSF框架)來提供系統之間的服務調用。緩存
目前淘寶前臺系統都是基於Java的MVC框架開發的(本身的WebX框架)如圖所示:安全
圖2.前臺系統基本結構性能優化
隨着淘寶網站的壯大,系統也面臨愈來愈多的挑戰,有些是業務發展帶來的挑戰,好比雙11雙12的大型活動,秒殺活動等突發流量的衝擊。還有一些非正常的訪問請求,例如網站常常受到攻擊和惡意請求。這些流量有些是能夠預測的,有些是不可預測的,不可防範的。服務器
像這種流量忽然暴增的狀況對系統的衝擊很大,有時候流量瞬間可達20w/s的QPS,因此如何讓系統更好更穩定的運行是一個大的挑戰。
4.1 靜態化系統
靜態化系統一般包含以下幾方面的特徵。
·一個頁面對應的URL一般是固定的。
·頁面中不能包含於瀏覽者相關的因素。
·頁面中不包含時間因素。服務端輸出的時間
·頁面中不包含地域因素。
·不包含Cookie等私有數據
4.2 爲何要進行靜態化設計
前面咱們分析了系統面臨的各類挑戰,這些挑戰都涉及性能優化,那性能優化爲何要進行靜態化這種架構設計呢?
由於,淘寶其實已經經歷了不少次系統的迭代升級,好比09年的靜態文件合併,前端頁面異步化和JSON化,10年的去DB依賴,引入K/V緩存和11年優化Velocity,BigPipe等都是優化的例子,可是這只是從Java系統層面上的優化,改進思路也一直是怎麼更快的獲取數據,並更快的將數據返回給用戶。可是當將系統全部數據所有緩存,而後將結果直接返回的時候咱們的系統不能知足預期的目標,也就說Java系統不可能達到每秒上萬的QPS。
因此,咱們判斷Java系統自己已經達到瓶頸,那咱們就必須跳過java系統,也就是讓請求儘可能不通過java系統,在前面的Web服務器層就直接返回是,因此,靜態化這種架構就成了必然選擇。
靜態化系統改變了緩存方式,直接緩存Http鏈接而不是緩存數據,Web代理服務器根據請求URL直接取出對應的HTTP響應頭和響應體直接返回,這個響應連Http都不用從新組裝了。一樣,http頭也不必定須要解析,這樣作到獲取數據最快。還改變了緩存的地方,不是java層面的緩存了,而是web服務器層上作緩存,因此屏蔽了java層面的弱點。
4.3 如何改造動態系統
以Detail系統爲例。
動靜分離:
·URL惟一化。Detail系統自然就是能夠作到URL惟一化,由於能夠以ID作惟一標識URL.
·分離於瀏覽者相關的因素,是否登錄與登錄信息等能夠單獨拆分,動態獲取。
·分離時間因素,服務端輸出的時間也能夠動態獲取。
·異步化地域因素。把Detail系統上的地域相關的作成異步方式來獲取。
·去掉Cookie.
動態內容結構化:
將動態內容json化。對於Detail系統雖然商品信息能夠緩存,不須要動態獲取可是也能夠將關鍵信息作成json的形式。
如何組裝動態內容:
兩種方式獲取:ESI和CSI
ESI:Web代理服務器上作動態請求內容,並將請求插入到靜態頁面上去。對服務端性能有影響可是用戶體驗好。
CSI:發起一個異步JS單獨向服務端獲取動態內容。這種方式使服務端性能更好,可是稍有延遲,用戶體驗稍差。
4.4 幾種靜態化方案的設計與選擇
考慮的問題:
·是否一致性hash分組?使用則可能會致使熱點問題,致使網絡瓶頸。
·是否使用ESI?使用對性能有影響,但用戶體驗好。
·是否使用物理機?內存更大,cpu更好,可是使集羣相對集中,致使網絡風險增長。
·誰來壓縮,在哪壓縮?增長Cache,必然增長數據的傳輸。
·網卡選擇?成本問題。
根據這幾個問題,可分別採用以下幾個方案:
方案1 採用Nginx+Cache+Java結構的虛擬機單機部署
結構圖以下:
圖3.Nginx+Cache+Java虛擬機單機部署結構圖
這是最簡單的靜態化方案,只須要在正常的架構上加一層Cache就行,優缺點以下:
優勢:
·沒有網絡瓶頸,不須要改造網絡
·機器增長,沒有網卡瓶頸
·機器數增多,故障風險減小
缺點:
·機器增長,緩存命中率降低
·緩存分散,失效難度增長
·Cache和JBoss都會搶內存
這種方案雖然簡單,可是可以解決熱點商品的訪問問題。
方案2 Nginx+Cache+Java結構實體機單機部署
結構圖以下:
圖4.Nginx+Cache+Java實體機單機部署結構圖
優勢以下:
·沒有網絡瓶頸,內存大
·減小Vish機器,提高命中率
·減小Cache失效的壓力
·減小Gzip的壓縮
方案3 統一Cache層
結構圖以下:
圖5.統一Cache層架構
優勢:
·減小多個應用接入使用Cache成本,接入的應用只維護本身的Java系統。
·統一Cache易於維護,好比配置,監控自動化。統一維護升級。
·共享內存最大化利用內存。
·有助於安全防禦。
4.5 如何解決失效問題:
緩存問題解決了,接下來應該解決失效問題了,採用主動失效和被動失效相結合的方式。
被動失效:
主要採用處理模板變動和對時效性要求不高的數據失效,採用設置Cache時間的長度這種自動失效方式,同時也要開發後臺管理界面手工失效這些cache.
主動失效:
·Cache失效中心監控數據庫表的變化,發送失效請求
·Java系統發佈,清空Cache
·Vm模板發佈,清空Cache
失效中心經過監控關鍵數據對應表的變動來發送請求給Cache,從而清楚Cache,其邏輯圖以下:
圖6.失效中心邏輯圖
4.6 服務端的靜態化方案的演變:CDN化(內容分發網絡)
將動態系統靜態化後,將Cache前移到CDN中,效果會更好。可是面臨以下幾個問題:
·失效問題。CDN分佈很廣,秒級的時間失效大量Cache難度很大
·命中率問題。CDN是分散的,Cache移到CDN中則命中率必然降低
·發佈更新問題。業務發佈和問題回滾排查也是須要考慮的方面。
解決方案:
失效問題:
類比服務端靜態化的失效方案,對CDN也採用相似的方式設計級聯失效結構,如圖:
圖7.級聯失效邏輯圖
命中率問題:
既然全部的CDN上放Detail不可行,那麼挑部分CDN節點便可。
節點條件:
·靠近訪問量比較集中的地方
·離主站較遠
·到主站的網絡好且穩定
·容量大
本次主要以淘寶的Detail爲背景,介紹了靜態化架構的設計,其中面臨的問題和解決辦法,雖然主要以Detail系統爲例,但其實架構的設計思路對全部大型的系統都是適用的。
慚愧,一年就寫了兩篇博客,最近在找實習,又想到寫博客了....
本次博客直接摘自許令波的深刻分析JavaWeb技術內幕的最後一章。有興趣的話你們能夠去看看這本書,寫的真的不錯。