一次線上事故對“本地檔案佇列非同步使用”的思考
事故描述
事故現象是部分服務http請求無響應。事故從發生到恢復,接近3個小時,事故過程中重啟應用服務,只能堅持幾分鐘到十幾分鍾,在真正發現問題前透過不斷重啟服務例項來支撐,慶幸的是核心服務沒有出現無響應的事故。
最終分析為AMQ出現故障,現象是MQ客戶端sendMessage後等待響應,但一直在等待,AMQ監控埠ok,控制檯也可以開啟,由於緊急沒有具體分析,直接重啟AMQ服務,切換master,透過驗證服務全部恢復。
這次故障大部分服務都使用了AMQ,但除了一個核心服務沒受到明顯影響外,其他使用AMQ的服務都不同程度的收到了影響,服務不可用。
<strong>
事後透過分析這個核心服務正式使用了本地檔案佇列避免了事故放大,逃過一劫,當時如果這個核心服務也受到影響就可想而知了,事故間期正直商戶業務高峰期,客戶估計要炸了,公司也會受到很大的損失。
</strong>
<strong>
此次事故比較嚴重,就是因為使用了本地檔案佇列有效隔離故障,使得影響面不大。假設(當然不希望發生了)核心業務沒有使用本地檔案佇列來隔離故障,整個下單、收銀服務將不可用,商戶無法營業,損失應該是數量級的。
</strong>
此次事故也證明了我當時的這個架構思路的正確性,主要體現在隔離和降級。
說說這個核心服務使用“本地檔案佇列”
我開發出來這個元件在這個團隊使用一直很穩定效果也很好。
實際上這個團隊使用“本地檔案佇列”的姿勢並不是我期望的,本身使用方法並沒有明顯不妥,只是會延遲訊息的消費,但這中方法可以很好的且有效的隔離故障。
就是在傳送AMQ訊息的方法上新增了@AsyncExecutable
,所以在入AMQ前先入隊“本地檔案佇列”,然後“本地檔案佇列”消費者再把訊息生產到AMQ。
這裡正是利用率“本地檔案佇列”的優點,比較可靠,只依賴於本地檔案系統,不會有網路故障的特性,近似不會被阻塞。
在事故分析中,實際上AMQ對該核心服務也受到影響,但由於採用了“本地檔案佇列”作為一級佇列,有效的隔離了對AMQ的網路依賴,所以沒有放大事故。事故中“本地檔案佇列”中訊息被積累,沒有被消費,重啟服務後才被消費,原因後面再分析。
再說說此次事故中服務不可用的原因
AMQ出現故障,現象是MQ客戶端sendMessage後等待響應,但一直在等待。
AMQ Client訊息的生產和Tomcat共用worker執行緒
AMQ Client訊息的生產沒有超時機制
AMQ Client訊息的生產採用同步傳送,非同步傳送有一些問題場景不太合適。
所以基於以上資訊,AMQ訊息的生產阻塞了Tomcat worker執行緒,最終導致worker執行緒被耗光而服務不可用。
在事故中透過執行緒堆疊資訊和Tomcat執行緒使用數統計也確定了執行緒很快被耗光而請求被阻塞。
另一個服務中採用了非同步執行緒池來生產AMQ訊息,但拒絕策略採用了CallerRunsPolicy
, 也是執行緒池執行緒很快被耗光而再耗光Tomcat worker執行緒,最終導致服務不可用。
事故產生的原因就是程式碼中沒有有效做網路呼叫的隔離和降級。
上面提到的核心服務也受到影響,參考《》,也是因為“本地檔案佇列”拒絕策略採用了CallerRunsPolicy
,最終導致執行緒池執行緒很快被耗光,而使用“本地檔案佇列”消費排程主執行緒,消費排程主執行緒被阻塞而無法消費“本地檔案佇列”訊息並生產到AMQ。但這裡和其他服務不同的是,主業務和AMQ的訊息生產是隔離的,主業務生產訊息到“本地檔案佇列”就返回,並不直接依賴AMQ。
本文中提到了使用本地檔案佇列的隔離姿勢。
後面再介紹使用本地檔案佇列的降級姿勢。
作者:鐵湯
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1343/viewspace-2820526/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一次線上事故,我頓悟了非同步的精髓非同步
- ThreadLocal引起的一次線上事故thread
- 記一次RocketMQ消費非順序訊息引起的線上事故MQ
- Hyperf redis 非同步佇列使用Redis非同步佇列
- synchronized 中的同步佇列與等待佇列synchronized佇列
- 如何在Ubuntu上使用FreeFileSync同步檔案Ubuntu
- 重大翻車現場,記一次線上事故
- 執行緒池運用不當的一次線上事故執行緒
- 佇列:佇列線上程池等有限資源池中的應用佇列
- kafka線上事故Kafka
- 處理線上RabbitMQ佇列阻塞MQ佇列
- 使用PowerShell比較本地文字檔案與Web上的文字檔案是否相同Web
- 一次JVM記憶體問題導致的線上事故JVM記憶體
- 記一次自定義starter引發的線上事故覆盤
- rsync同步和備份檔案到本地
- 使用Unison 同步檔案
- 佇列順序性引發的思考佇列
- 檔案包含漏洞(本地包含配合檔案上傳)
- 記一次Lombok的Setter過載方法造成的事故及思考Lombok
- 一次線上問題排查所引發的思考
- AQS佇列同步器AQS佇列
- 記一次 vue 的非同步更新佇列導致記憶體洩漏Vue非同步佇列記憶體
- 學成線上專案總結 - Day5 RabbitMQ訊息佇列MQ佇列
- 非對稱加密演算法的思考加密演算法
- AbstractQueuedSynchronizer 佇列同步器(AQS)佇列AQS
- Java 佇列同步器 AQSJava佇列AQS
- 自定義單連結串列佇列的基本介面函式(非迴圈佇列)佇列函式
- 一次因生產事故與chatGpt的對話ChatGPT
- Redis 應用-非同步訊息佇列與延時佇列Redis非同步佇列
- 第一次線上 OOM 事故,竟和 where 1 = 1 有關OOM
- 分享一個本人的私密檔案加密方法:用php 對windows 上的自己的本地私密檔案進行加密。加密PHPWindows
- 【MySQL】記一次線上重大事故:二狗子竟然把線上資料庫刪了!!MySql資料庫
- 訊息佇列Kafka「檢索元件」重磅上線!佇列Kafka元件
- 小程式使用 Promise.all 完成檔案非同步上傳Promise非同步
- 深入理解webpack的chunkId對線上快取的思考Web快取
- 使用ln同步檔案內容,支援忽略檔案
- RocketMQ -- 訊息消費佇列與索引檔案MQ佇列索引
- 使用 SAP UI5 FileUploader 控制元件上傳本地檔案UI控制元件