事故描述
事故現(xiàn)象是部分服務(wù)http請(qǐng)求無響應(yīng)渣叛。事故從發(fā)生到恢復(fù)丈秩,接近3個(gè)小時(shí),事故過程中重啟應(yīng)用服務(wù)淳衙,只能堅(jiān)持幾分鐘到十幾分鐘蘑秽,在真正發(fā)現(xiàn)問題前通過不斷重啟服務(wù)實(shí)例來支撐饺著,慶幸的是核心服務(wù)沒有出現(xiàn)無響應(yīng)的事故。
最終分析為AMQ出現(xiàn)故障肠牲,現(xiàn)象是MQ客戶端sendMessage后等待響應(yīng)幼衰,但一直在等待,AMQ監(jiān)控端口ok缀雳,控制臺(tái)也可以打開渡嚣,由于緊急沒有具體分析,直接重啟AMQ服務(wù)肥印,切換master识椰,通過驗(yàn)證服務(wù)全部恢復(fù)。
這次故障大部分服務(wù)都使用了AMQ深碱,但除了一個(gè)核心服務(wù)沒受到明顯影響外腹鹉,其他使用AMQ的服務(wù)都不同程度的收到了影響,服務(wù)不可用敷硅。
<strong>
事后通過分析這個(gè)核心服務(wù)正式使用了本地文件隊(duì)列避免了事故放大功咒,逃過一劫,當(dāng)時(shí)如果這個(gè)核心服務(wù)也受到影響就可想而知了绞蹦,事故間期正直商戶業(yè)務(wù)高峰期力奋,客戶估計(jì)要炸了,公司也會(huì)受到很大的損失坦辟。
</strong>
<strong>
此次事故比較嚴(yán)重刊侯,就是因?yàn)槭褂昧?strong>本地文件隊(duì)列有效隔離故障,使得影響面不大锉走。假設(shè)(當(dāng)然不希望發(fā)生了)核心業(yè)務(wù)沒有使用本地文件隊(duì)列來隔離故障滨彻,整個(gè)下單、收銀服務(wù)將不可用挪蹭,商戶無法營業(yè)亭饵,損失應(yīng)該是數(shù)量級(jí)的。
</strong>
此次事故也證明了我當(dāng)時(shí)的這個(gè)架構(gòu)思路的正確性梁厉,主要體現(xiàn)在隔離和降級(jí)辜羊。
說說這個(gè)核心服務(wù)使用“本地文件隊(duì)列”
我開發(fā)出來這個(gè)組件在這個(gè)團(tuán)隊(duì)使用一直很穩(wěn)定效果也很好。
實(shí)際上這個(gè)團(tuán)隊(duì)使用“本地文件隊(duì)列”的姿勢(shì)并不是我期望的词顾,本身使用方法并沒有明顯不妥八秃,只是會(huì)延遲消息的消費(fèi),但這中方法可以很好的且有效的隔離故障肉盹。
就是在發(fā)送AMQ消息的方法上添加了@AsyncExecutable
昔驱,所以在入AMQ前先入隊(duì)“本地文件隊(duì)列”,然后“本地文件隊(duì)列”消費(fèi)者再把消息生產(chǎn)到AMQ上忍。
![](http://7xiovs.com1.z0.glb.clouddn.com/async.png)
這里正是利用率“本地文件隊(duì)列”的優(yōu)點(diǎn)骤肛,比較可靠纳本,只依賴于本地文件系統(tǒng),不會(huì)有網(wǎng)絡(luò)故障的特性腋颠,近似不會(huì)被阻塞繁成。
在事故分析中,實(shí)際上AMQ對(duì)該核心服務(wù)也受到影響淑玫,但由于采用了“本地文件隊(duì)列”作為一級(jí)隊(duì)列巾腕,有效的隔離了對(duì)AMQ的網(wǎng)絡(luò)依賴,所以沒有放大事故混移。事故中“本地文件隊(duì)列”中消息被積累祠墅,沒有被消費(fèi),重啟服務(wù)后才被消費(fèi)歌径,原因后面再分析。
再說說此次事故中服務(wù)不可用的原因
- AMQ出現(xiàn)故障亲茅,現(xiàn)象是MQ客戶端sendMessage后等待響應(yīng)回铛,但一直在等待。
- AMQ Client消息的生產(chǎn)和Tomcat共用worker線程
- AMQ Client消息的生產(chǎn)沒有超時(shí)機(jī)制
- AMQ Client消息的生產(chǎn)采用同步發(fā)送克锣,異步發(fā)送有一些問題場景不太合適茵肃。
所以基于以上信息,AMQ消息的生產(chǎn)阻塞了Tomcat worker線程袭祟,最終導(dǎo)致worker線程被耗光而服務(wù)不可用验残。
在事故中通過線程堆棧信息和Tomcat線程使用數(shù)統(tǒng)計(jì)也確定了線程很快被耗光而請(qǐng)求被阻塞。
另一個(gè)服務(wù)中采用了異步線程池來生產(chǎn)AMQ消息巾乳,但拒絕策略采用了CallerRunsPolicy
, 也是線程池線程很快被耗光而再耗光Tomcat worker線程您没,最終導(dǎo)致服務(wù)不可用。
事故產(chǎn)生的原因就是代碼中沒有有效做網(wǎng)路調(diào)用的隔離和降級(jí)胆绊。
上面提到的核心服務(wù)也受到影響氨鹏,參考《本地文件隊(duì)列-異步隔離》,也是因?yàn)?strong>“本地文件隊(duì)列”拒絕策略采用了CallerRunsPolicy
压状,最終導(dǎo)致線程池線程很快被耗光仆抵,而使用“本地文件隊(duì)列”消費(fèi)調(diào)度主線程,消費(fèi)調(diào)度主線程被阻塞而無法消費(fèi)“本地文件隊(duì)列”消息并生產(chǎn)到AMQ种冬。但這里和其他服務(wù)不同的是镣丑,主業(yè)務(wù)和AMQ的消息生產(chǎn)是隔離的,主業(yè)務(wù)生產(chǎn)消息到“本地文件隊(duì)列”就返回娱两,并不直接依賴AMQ莺匠。
本文中提到了使用本地文件隊(duì)列的隔離姿勢(shì)。
后面再介紹使用本地文件隊(duì)列的降級(jí)姿勢(shì)谷婆。