掃描下方海報二維碼,試聽課程:
前端
(課程詳細大綱,請參見文末)面試
=========================================架構
本文來源於公衆號狸貓技術窩的專欄:
併發
是做者救火隊隊長開放的試讀文章高併發
救火隊隊長,阿里資深技術專家oop
=========================================
性能
本週咱們的一個重點就是給你們再次強調JVM頻繁GC對系統性能的危害性。大數據
所以在分析完JVM發生GC的場景以及原理,以及梳理清楚各類GC名詞的概念和觸發時機以後,咱們就能夠來用兩個以前咱們線上系統真實的案例來給你們再次在腦海中強化一下頻繁GC帶來的性能問題。優化
先給你們說一下咱們線上一個真實的生產系統,是一個服務於百萬級商家的BI系統。
這個所謂BI系統,不少開發業務系統的同窗可能沒接觸過,因此簡單介紹一下他的背景。
簡單來講,好比你是一個平臺,而後有數十萬甚至上百萬的商家在你的平臺上作生意,會使用你的這個平臺系統
此時必定會產生大量的數據,基於這些數據咱們須要爲商家提供一些數據報表
好比:每一個商家天天有多少訪客?有多少交易?付費轉化率是多少?
固然實際狀況會比這個簡單幾句話複雜不少,這裏就是簡單說一下它的概念。
所以就須要一套BI系統,所謂BI,英文全稱是「Business Intelligence」,也就是「商業智能」,聽起來是否是特別的高大上?
其實也別想的過高大上了,說白了,就是把一些商家平時平常經營的數據收集起來進行分析,而後把各類數據報表展現給商家的一套系統。
所謂「商務智能」,指的就是給你看一些數據報表,而後讓你平時可以更好的瞭解本身的經營情況,而後讓老闆「智能」的去調整經營策略,提高業績。
因此相似這樣的一個BI系統,大體的運行邏輯以下所示,首先從咱們提供給商家平常使用的一個平臺上會採集出來不少商家平常經營的數據。
以下圖所示:
接着就能夠對這些經營數據依託各類大數據計算平臺,好比Hadoop、Spark、Flink等技術進行海量數據的計算,計算出來各類各樣的數據報表。
以下圖所示:
而後咱們須要將計算好的各類數據分析報表都放入一些存儲中,好比MySQL、Elastcisearch、HBase均可以存放相似的數據
以下圖所示:
最後一步,就是基於MySQL、HBase、Elasticsearch中存儲的數據報表,基於Java開發出來一個BI系統。
而後經過這個系統,把各類存儲好的數據暴露給前端,容許前端基於各類條件對存儲好的數據進行復雜的篩選和分析。
以下圖所示:
咱們在這裏重點做爲案例分析的就是上述場景中的BI系統,其餘環節都跟大數據相關的技術是有關聯的,暫時先不涉及,將來有機會能夠給你們出更多的課程來闡述那些技術。
剛開始,這個BI系統使用的商家是很少的。
由於你們要知道,即便在一個龐大的互聯網大廠裏,雖然大廠自己積累了大量的商家,可是你要是針對他們上線一個付費的產品,剛開始未必全部人都買帳
因此一開始系統上線大概就少數商家在使用,好比就幾千個商家。
所以剛開始系統部署的很是簡單,就是用幾臺機器來部署了上述的BI系統,機器都是普通的4核8G的配置
而後在這個配置之下,通常來講給堆內存中的新生代分配的內存都在1.5G左右,Eden區大概也就1G左右的空間
以下圖所示:
其實剛開始,在少數商家的量級之下,這個系統是沒多大問題的,運行的很是良好,但問題就出在使用系統的商家數量開始暴漲的時候。
忽然使用系統的商家開始愈來愈多,好比給你們舉個例子,當商家的數量級達到幾萬的時候。
此時要給你們說明一個此類BI系統的特色,就是在BI系統中有一種數據報表,他是支持前端頁面有一個JS腳本,自動每隔幾秒鐘就發送請求到後臺刷新一下數據的。
這種報表稱之爲「實時數據報表」,以下圖所示:
那麼你們能夠設想一下,假設僅僅就幾萬商家做爲你的系統用戶,極可能同一時間打開那個實時報表的商家就有幾千個
而後每一個商家打開實時報表以後,前端頁面都會每隔幾秒鐘發送請求到後臺來加載最新數據。
這時基本上會出現你的BI系統部署的每臺機器每秒的請求會達到幾百個,這裏就假設每秒500個請求。
而後每一個請求會加載出來一張報表須要的大量數據,由於BI系統可能還須要針對那些數據進行內存中的現場計算加工一下,才能返回給前端頁面展現。
根據咱們以前的測算,每一個請求大概須要加載出來100kb的數據進行計算,所以每秒500個請求,就須要加載出來50MB的數據到內存中進行計算。
以下圖所示:
其實你們都已經發現上述系統的問題了,在上述系統運行模型下,基本上每秒會加載50MB的數據到Eden區中。
也就是說,只要區區200s,也就是3分鐘左右的時間,就會迅速填滿Eden區,而後觸發一次Young GC對新生代進行垃圾回收。
固然1G左右的Eden進行Young GC其實速度相對是比較快的,可能也就幾十ms的時間就能夠搞定了。
因此以前也分析過,這其實對系統性能影響並不大。並且上述BI系統場景下,基本上每次Young GC後存活對象可能就幾十MB,甚至是幾MB。
因此若是僅僅只是這樣的話,你們可能會看到以下場景,BI系統運行幾分鐘事後,就會忽然卡頓個10ms,可是對終端用戶和系統性能幾乎是沒有影響的
以下圖:
針對這樣的一套系統,後來隨着愈來愈多的商家來使用,併發壓力愈來愈大,甚至高峯期會有每秒10萬的併發壓力
若是仍是用4核8G的機器來支撐,那麼可能須要部署上百臺機器來抗住每秒10萬的高併發壓力。
因此通常針對這種狀況,咱們會提高機器的配置。
自己BI系統就是很是吃內存的系統,因此咱們將部署的機器全面提高到了16核32G的高配置機器上去。每臺機器能夠抗個每秒幾千請求,此時只要部署二三十臺機器就能夠了。
可是此時問題就來了,若是要是用大內存機器的話,那麼新生代至少會分配到20G的大內存,Eden區也會佔據16G以上的內存空間。
以下圖所示:
此時每秒幾千請求的話,每秒大概會加載到內存中幾百MB的數據,那麼大概可能幾十秒,甚至1分鐘左右就會填滿Eden區,就須要執行Young GC了。
此時Young GC要回收那麼大的內存,速度會慢不少,也許此時就會致使系統卡頓個幾百毫秒,或者1秒鐘
以下圖所示:
那麼你要是系統卡頓時間過長,必然會致使瞬間不少請求積壓排隊,嚴重的時候會致使線上系統時不時出現前端請求超時的問題,就是前端請求以後發現一兩秒後還沒返回就超時報錯了。
因此當時對這個系統的一個優化,就是採用G1垃圾回收器來應對大內存的Young GC過慢的問題。
(ps:關於G1回收器,咱們此前已經經過一步一圖的方式,詳細闡述了其工做原理,若是忘記了的同窗,能夠回看一下)
能夠對G1設置一個預期的GC停頓時間,好比100ms,讓G1保證每次Young GC的時候最多停頓100ms,避免影響終端用戶的使用。
此時效果是很是顯著的,G1會自動控制好在每次Young GC的時候就回收一部分Region,確保GC停頓時間控制在100ms之內
這樣的話,也許Young GC的頻率會更高一些,可是每次停頓時間很小,這樣對系統影響就不大了。
本文用一個案例,其實就想說明一個問題,一般Young GC哪怕發生的頻繁一些,其實通常都對系統形成不了太大的影響
只有在你機器內存特別大的時候,才須要注意Young GC也可能會致使比較長時間的停頓,此時針對大內存機器一般建議採用G1垃圾回收器。
看到這裏,給你們留一個小思考題,去想辦法看看本身線上系統:
多長時間發生一次Young GC?
Young GC耗時多久?
而後你以爲它對你的系統影響大嗎?
END
點擊下方連接,瞭解更多專欄詳情:
或者直接關注公衆號:石杉的架構筆記,點擊下方菜單欄-訓練營查看
《21天互聯網Java進階面試訓練營(分佈式篇)》詳細目錄,掃描圖片末尾的二維碼,試聽課程