溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析

發(fā)布時(shí)間:2021-10-23 16:38:53 來(lái)源:億速云 閱讀:226 作者:柒染 欄目:開(kāi)發(fā)技術(shù)

這篇文章給大家介紹JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

業(yè)務(wù)場(chǎng)景介紹

先簡(jiǎn)單說(shuō)說(shuō)線上生產(chǎn)系統(tǒng)的一個(gè)背景,因?yàn)閮H僅是文章作為案例來(lái)講,所以弱化大量的業(yè)務(wù)背景。

簡(jiǎn)單來(lái)說(shuō),這是一套分布式系統(tǒng),系統(tǒng) A 需要將一個(gè)非常核心以及關(guān)鍵的數(shù)據(jù)通過(guò)網(wǎng)絡(luò)請(qǐng)求,傳輸給另外一個(gè)系統(tǒng) B。

這里其實(shí)就考慮到了一個(gè)問(wèn)題,如果系統(tǒng) A 剛剛將核心數(shù)據(jù)傳遞給了系統(tǒng) B,結(jié)果系統(tǒng) B 莫名其妙宕機(jī)了,豈不是會(huì)導(dǎo)致數(shù)據(jù)丟失?

所以在這個(gè)分布式系統(tǒng)的架構(gòu)設(shè)計(jì)中,采取了非常經(jīng)典的一個(gè) Quorum 算法。

這個(gè)算法簡(jiǎn)單來(lái)說(shuō),就是系統(tǒng) B 必須要部署奇數(shù)個(gè)節(jié)點(diǎn),比如說(shuō)至少部署 3 臺(tái)機(jī)器,或者是 5 臺(tái)機(jī)器,7 臺(tái)機(jī)器,類(lèi)似這樣子。

然后系統(tǒng) A 每次傳輸一個(gè)數(shù)據(jù)給系統(tǒng),都必須要對(duì)系統(tǒng) B 部署的全部機(jī)器都發(fā)送請(qǐng)求,將一份數(shù)據(jù)傳輸給系統(tǒng)B部署的所有機(jī)器。

要判定系統(tǒng) A 對(duì)系統(tǒng) B 的一次數(shù)據(jù)寫(xiě)是成功的,要求系統(tǒng) A 必須在指定時(shí)間范圍內(nèi)對(duì)超過(guò) Quorum 數(shù)量的系統(tǒng) B 所在機(jī)器傳輸成功。

舉個(gè)例子,假設(shè)系統(tǒng) B 部署了 3 臺(tái)機(jī)器,那么他的 Quorum 數(shù)量就是:3 / 2 + 1 = 2,也就是說(shuō)系統(tǒng) B 的 Quorum 數(shù)量就是:所有機(jī)器數(shù)量 / 2 + 1。

所以系統(tǒng) A 要判定一個(gè)核心數(shù)據(jù)是否寫(xiě)成功,如果系統(tǒng) B 一共部署了 3 臺(tái)機(jī)器的話,那么系統(tǒng) A 必須在指定時(shí)間內(nèi)收到 2 臺(tái)系統(tǒng) B 所在機(jī)器返回的寫(xiě)成功的響應(yīng)。

此時(shí)系統(tǒng) A 才能認(rèn)為這條數(shù)據(jù)對(duì)系統(tǒng) B 是寫(xiě)成功了。這個(gè)就是所謂的 Quorum 機(jī)制。

也就是說(shuō),分布式架構(gòu)下,系統(tǒng)之間傳輸數(shù)據(jù),一個(gè)系統(tǒng)要確保自己給另外一個(gè)系統(tǒng)傳輸?shù)臄?shù)據(jù)不會(huì)丟失,必須要在指定時(shí)間內(nèi),收到另外一個(gè)系統(tǒng) Quorum(大多數(shù))數(shù)量的機(jī)器響應(yīng)說(shuō)寫(xiě)成功。

這套機(jī)制實(shí)際上在很多分布式系統(tǒng)、中間件系統(tǒng)中都有非常廣泛的使用,我們線上的分布式系統(tǒng)也是采用了這個(gè) Quorum 機(jī)制在兩個(gè)系統(tǒng)之間傳輸數(shù)據(jù)。

給大家上一張圖,一起來(lái)看一下這套架構(gòu)長(zhǎng)啥樣:

JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析

如上圖所示,圖中很清晰的展示了系統(tǒng) A 和系統(tǒng) B 之間傳輸一份數(shù)據(jù)時(shí)的 Quorum 機(jī)制。

接下來(lái),我們用代碼給大家展示一下,上面的 Quorum 寫(xiě)機(jī)制在代碼層面大概是什么樣子的。

PS:因?yàn)閷?shí)際這套機(jī)制涉及大量的底層網(wǎng)絡(luò)傳輸、通信、容錯(cuò)、優(yōu)化的東西,所以下面代碼經(jīng)過(guò)了大幅度簡(jiǎn)化,僅僅表達(dá)出了一個(gè)核心的意思。

JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析
JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析

上面就是經(jīng)過(guò)大幅精簡(jiǎn)后的代碼,不過(guò)核心的意思是表達(dá)清晰了。大家可以仔細(xì)看兩遍,其實(shí)還是很容易弄懂的。

這段代碼含義很簡(jiǎn)單,說(shuō)白了就是異步開(kāi)啟線程發(fā)送數(shù)據(jù)給系統(tǒng) B 所有的機(jī)器,同時(shí)進(jìn)入一個(gè) while 循環(huán)等待系統(tǒng) B 的 Quorum 數(shù)量的機(jī)器返回響應(yīng)結(jié)果。

如果超過(guò)指定超時(shí)時(shí)間還沒(méi)收到預(yù)期數(shù)量的機(jī)器返回結(jié)果,那么就判定系統(tǒng) B 部署的集群出現(xiàn)故障,接著讓系統(tǒng) A 直接退出,相當(dāng)于系統(tǒng) A 宕機(jī)。

整個(gè)代碼,就是這么個(gè)意思!

問(wèn)題凸現(xiàn)

光是看代碼其實(shí)沒(méi)啥難的,但是問(wèn)題就在于線上運(yùn)行的時(shí)候,可不是跟你寫(xiě)代碼的時(shí)候想的一樣簡(jiǎn)單。

有一次線上生產(chǎn)系統(tǒng)運(yùn)行的過(guò)程中,整體系統(tǒng)負(fù)載都很平穩(wěn),本來(lái)是不應(yīng)該有什么問(wèn)題,但是結(jié)果突然收到報(bào)警,說(shuō)系統(tǒng) A 突然宕機(jī)了。

然后就開(kāi)始進(jìn)行排查,左排查右排查,發(fā)現(xiàn)系統(tǒng) B 集群都好好的,不應(yīng)該有問(wèn)題。

然后再查查系統(tǒng) A,發(fā)現(xiàn)系統(tǒng) A 別的地方也沒(méi)什么問(wèn)題。***結(jié)合系統(tǒng) A 自身的日志,以及系統(tǒng) A 的 JVM FullGC 進(jìn)行垃圾回收的日志,我們才算是搞清楚了具體的故障原因。

定位問(wèn)題

其實(shí)原因非常的簡(jiǎn)單,就是系統(tǒng) A 在線上運(yùn)行一段時(shí)間后,會(huì)偶發(fā)性的進(jìn)行長(zhǎng)時(shí)間 Stop the World 的 JVM FullGC,也就是大面積垃圾回收。

但是,此時(shí)會(huì)造成系統(tǒng) A 內(nèi)部的工作線程大量的卡頓,不再工作。要等 JVM FullGC 結(jié)束之后,工作線程才會(huì)恢復(fù)運(yùn)作。

我們來(lái)看下面那個(gè)代碼片段:

JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析

但是這種系統(tǒng) A 的莫名宕機(jī)是不正確的,因?yàn)槿绻麤](méi)有 JVM FullGC,本來(lái)上面那個(gè) if 語(yǔ)句是不會(huì)成立的。

它會(huì)停頓 1 秒鐘進(jìn)入下一輪 while 循環(huán),接著就可以收到系統(tǒng) B 返回的 Quorum 數(shù)量的結(jié)果,這個(gè) while 循環(huán)就可以中斷,繼續(xù)運(yùn)行了。

結(jié)果因?yàn)槌霈F(xiàn)了 JVM FullGC 卡頓了幾十秒,導(dǎo)致莫名其妙就觸發(fā)了 if 判斷的執(zhí)行,系統(tǒng) A 莫名其妙就退出宕機(jī)了。

所以,線上的 JVM FullGC 導(dǎo)致的系統(tǒng)長(zhǎng)時(shí)間卡頓,真是造成系統(tǒng)不穩(wěn)定運(yùn)行的隱形殺手之一啊!

解決問(wèn)題

至于上述代碼穩(wěn)定性的優(yōu)化,也很簡(jiǎn)單。我們只要在代碼里加入一些東西,監(jiān)控一下上述代碼中是否發(fā)生了 JVM FullGC。

如果發(fā)生了 JVM FullGC,就自動(dòng)延長(zhǎng) expireTime 就可以了。

比如下面代碼的改進(jìn):

JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析

通過(guò)上述代碼的改進(jìn),就可以有效的優(yōu)化線上系統(tǒng)的穩(wěn)定性,保證其在 JVM FullGC 發(fā)生的情況下,也不會(huì)隨意出現(xiàn)異常宕機(jī)退出的情況了。

關(guān)于JVM FullGC引發(fā)的宕機(jī)事故的實(shí)例分析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI