《京東活動系統億級流量應對之術》要點:
本文介紹了京東活動系統億級流量應對之術,希望對您有用。如果有疑問,可以聯系我們。
作者:干天星,2012年初加入京東,先后在京東審計、搭配購、jshop活動系統等項目從事系統研發和架構工作.目前主要負責jshop活動系統架構升級,以及jshop數據中心實現運算架構設計.對構建高并發web架構,以及高性能實時大數據運算,有一定的見解.入職前有過5年電信傳統行業開發、架構經驗.
京東活動系統是一個可在線編輯、實時編輯更新和發布新活動,并對外提供頁面訪問服務的系統,地址如http://sale.jd.com/***.html.其高時效性、靈活性等特征,極受青睞,已發展成京東幾個重要流量入口之一.近幾次大促,系統所承載的PV均為數億以上.隨著京東業務的高速發展,京東活動系統的壓力會越來越大.急需要一個更高效,穩定的系統架構,來支持業務的高速發展.本文主要對活動頁面瀏覽方面的性能,進行探討.
活動頁面瀏覽性能提升的難點:
活動與活動之間差異很大,不像商品頁有固定的模式.每個頁面能抽取的公共部分有限,可復用性差;
活動頁面內容多樣,業務繁多.依賴大量外部業務接口,數據很難做到閉環.外部接口的性能,以及穩定性,嚴重制約了活動頁的渲染速度、穩定性;
經過多年在該系統下的開發實踐,提出“頁面渲染與頁面瀏覽異步化”的思想,頁面渲染是把渲染好的整頁數據放到redis或者硬盤里了,頁面瀏覽是從redis或者硬盤里取靜態的頁面,并以此為指導,對該系統進行架構升級改造.通過近幾個月的運行,各方面性能都有顯著提升.在分享”新架構”之前,先看看我們現有web系統的架構現狀.
*瀏覽服務
以京東活動系統架構的演變為例,這里沒有畫出具體的業務邏輯,只是簡單的描述下架構.
我們會在消耗性能的地方加緩存,這里對部分查庫操作加redis緩存.
并且對頁面進行整頁redis緩存:由于活動頁面內容繁多,渲染一次頁面的成本是很高.這里可以考慮把渲染好的活動內容整頁緩存起來,下次請求到來時,如果緩存中有值,直接獲取緩存返回.
以上是系統應用服務層面架構演進的,簡單示意.為了減少應用服務器的壓力,可以在應用服務器前面,加cdn和nginx的proxy_cache,減少回源率.
整體架構(老)
除了“瀏覽服務”外,老架構還做了其他兩個大的優化:“接口服務”、“靜態服務”
接口服務分兩類,直接讀redis緩存和調用外部接口.這里可以對直接讀redis的接口采用nginx+lua(openresty)進行優化,不做詳細講解.本次分享主要對“瀏覽服務”架構.
在講新架構之前先看看新老架構下的新能對比.
*老架構瀏覽服務性能
擊穿cdn緩存、nginx緩存,回源到應用服務器的流量大約為20%-40%之間,這里的性能對比,只針對回源到應用服務器的部分.
瀏覽方法TP99如下(物理機)
TP99? 1000ms左右,且抖動幅度很大,內存使用近70%,cpu 45%左右.1000ms內沒有緩存,有阻塞甚至掛掉的風險.
* 新架構瀏覽服務性能
本次2016 618采用新架構支持,瀏覽TP99如下(分app端活動和pc端活動)
移動活動瀏覽TP99穩定在8ms, PC活動瀏覽TP99 穩定在15ms左右.全天幾乎一條直線,沒有性能抖動.
新架構支持,服務器(docker)cpu性能如下
cpu消耗一直平穩在1%,幾乎沒有抖動.
對比結果:新架構TP99從1000ms降低到15ms,cpu消耗從45%降低到1%,新架構性能得到質的提升.
why!!!下面我們就來揭開新架構的面紗.
*頁面渲染與頁面瀏覽異步化
再來看之前的瀏覽服務架構,20%-40%的頁面請求會重新渲染頁面,渲染需要重新計算、查詢、創建對象等導致cpu、內存消耗增加,TP99性能下降.
如果能保證每次請求都能獲取到redis整頁緩存,這些性能問題就都不存在了.即:頁面渲染與頁面瀏覽異步.
*直接改造后的問題以及解決方案
理想情況下,如果頁面數據變動可以通過手動觸發渲染(頁面發布新內容)、外部數據變化通過監聽mq自動觸發渲染.
但是有些外部接口不支持mq、或者無法使用mq,比如活動頁面置入的某個商品,這個商品名稱變化.
為了解決這個問題,view工程每隔指定時間,向engine發起重新渲染請求-最新內容放入redis.下一次請求到來時即可獲取到新內容.由于活動很多,也不能確定哪些活動在被訪問,所以不建議使用timer.通過加一個緩存key來實現,處理邏輯如下.
好處就是,只對有訪問的活動定時重新發起渲染.
*整理架構(不包含業務)
view工程職責:
直接從緩存或者硬盤中獲取靜態HTML返回,如果沒有返回錯誤頁面(文件系統的存取性能比較低,超過100ms級別,這里沒有使用);
根據緩存key2是否過期,判斷是否向engine重新發起渲染(如果你的項目外面接口都支持mq,這個功能就不需要了).
engine工程職責:
渲染活動頁面,把結果放到硬盤、redis.
publish工程、mq職責:
頁面發生變化,向engine重新發起渲染,具體的頁面邏輯,這里不做講解.
Engine工程的工作就是當頁面內容發生變化時,重新渲染頁面,并將整頁內容放到redis,或者推送到硬盤.
* view工程架構(redis版)
View工程的工作,就是根據鏈接從redis中獲取頁面內容返回.
* view工程架構 (硬盤版)
兩個版本對比
Redis版
優點:接入簡單、性能好,尤其是在大量頁面情況下,沒有性能抖動.單個dockertps達到700;
缺點:嚴重依賴京東redis服務,如果redis服務出現問題,所有頁面都無法訪問.
硬盤版
優點:不依賴任何其他外部服務,只要應用服務不掛、網絡正常就可以對外穩定服務;在頁面數量不大的情況下,性能優越.單個dockertps達到2000;
缺點:在頁面數據量大的情況下(系統的所有活動頁有xx個G左右),磁盤io消耗增加(這里采用的javaio,如果采用nginx+lua(OpenResty),io消耗應該會控制在10%以內).
解決方案
對所有頁面訪問和存儲采用urlhash方式,所有頁面均勻分配到各個應用服務器上;
采用nginx+lua(OpenResty)利用nginx的異步io,代替javaio.
*Openresty+硬盤版
現在通過nginx+lua(OpenResty)做應用服務,所具有的高并發處理能力、高性能、高穩定性已經越來越受青睞.通過上述講解,view工程沒有任何業務邏輯.可以很輕易的就可以用lua實現,從redis或者硬盤獲取頁面,實現更高效的web服務.
通過測試對比,view工程讀本地硬盤的速度,比讀redis還要快(同一個頁面,讀redis是15ms,硬盤是8ms).所以終極版架構我選擇用硬盤,redis做備份,硬盤讀不到時在讀redis.
這里前置機的urlhash是自己實現的邏輯,engine工程采用同樣的規則推送到view服務器硬盤即可,具體邏輯這里不細講.后面有時間再單獨做一次分享.
優點:
具備硬盤版的全部優點,同時去掉tomcat,直接利用nginx高并發能力,以及io處理能力;
各項性能、以及穩定性達到最優.
缺點:
硬盤壞掉,影響訪問;
方法監控,以及日志打印,需使用lua腳本重寫.
無論是redis版、硬盤版、openresty+硬盤版,基礎都是頁面渲染與頁面瀏覽異步化.
優勢:
從事開發已有近10載,一直就像寄生蟲一樣吸取著網絡上的資源.前段時間受“張開濤”大神所托,對活動系統新架構做了一次簡單整理分享給大家,希望能給大家帶來一絲幫助.第一次在網上做分享,難免有些沒有考慮周全的地方,以后會慢慢的多分享一些自己的心得,大家一起成長.最后再來點心靈雞湯...
文章出處:開濤的博客(訂閱號ID:kaitao-1234567)
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4387.html