- 線上高峰期會(huì)出現(xiàn)消息堆積嗎
- 壓測(cè)環(huán)境下出現(xiàn)消費(fèi)堆積怎么解決
2.1 消費(fèi)者數(shù)量少
2.2 消費(fèi)者數(shù)量不少禀倔,壓力在機(jī)器CPU或者內(nèi)存
2.3 消費(fèi)者數(shù)量不少茫船,壓力在數(shù)據(jù)庫(kù)
2.4 消費(fèi)者數(shù)量不少恋腕,壓力在接口 - 線上出現(xiàn)消息堆積的事故
3.1 案例1—消息發(fā)送unack
3.2 案例二—消息出現(xiàn)error異常 - 怎么處理線上的消息堆積事故
- 代碼中如何防止消息堆積
5.1 消息unack導(dǎo)致消息堆積
5.2 消息出現(xiàn)ERROR異常
作為一個(gè)程序員歼捏,也是經(jīng)歷了幾次MQ消息堆積的事故的处嫌。
理論上說(shuō)啥寇,消息堆積的兩個(gè)原因:
- 生產(chǎn)者生產(chǎn)消息太快偎球;
- 消費(fèi)者消費(fèi)消息太慢;
但是辑甜,真正會(huì)出現(xiàn)消息堆積的衰絮,大多數(shù)都是代碼出現(xiàn)了bug,導(dǎo)致消費(fèi)者消息速度過(guò)慢磷醋。
1. 線上高峰期會(huì)出現(xiàn)消息堆積嗎
若是MQ在線上經(jīng)常出現(xiàn)消息堆積猫牡,那么MQ早被淘汰了。
MQ三大作用:異步邓线、削峰淌友、解耦。
作為一個(gè)中大型項(xiàng)目來(lái)說(shuō)褂痰,功能測(cè)試是最基本的亩进。對(duì)項(xiàng)目來(lái)說(shuō),每周都會(huì)有壓力測(cè)試缩歪,上一個(gè)重要的功能前归薛,也都會(huì)在壓力測(cè)試達(dá)標(biāo)的情況下才能正式上線。
而壓力測(cè)試保證了系統(tǒng)在高峰期的水平下依舊可以正常穩(wěn)定的工作匪蝙。
并且線上環(huán)境會(huì)配置限流策略主籍,例如壓測(cè)環(huán)境下系統(tǒng)核心鏈路為200并發(fā)2000TPS。那么在系統(tǒng)上線之后逛球,會(huì)配置相應(yīng)的限流熔斷策略千元,保證系統(tǒng)不會(huì)出現(xiàn)崩潰。
也就保證了:在線上高峰期情況下颤绕,不會(huì)存在生產(chǎn)者生產(chǎn)過(guò)快幸海、或者消費(fèi)者消費(fèi)過(guò)慢導(dǎo)致消息堆積的情況祟身。
2. 壓測(cè)環(huán)境下出現(xiàn)消費(fèi)堆積怎么解決
壓測(cè)環(huán)境出現(xiàn),就要解決這個(gè)問(wèn)題物独,首先肯定不是生產(chǎn)者的問(wèn)題袜硫,因?yàn)槲催_(dá)到預(yù)期的壓測(cè)數(shù)值。
那么是消費(fèi)者出現(xiàn)的問(wèn)題:
- 消費(fèi)者數(shù)量太少挡篓?
- 消費(fèi)者數(shù)量不少婉陷,是調(diào)用接口或者數(shù)據(jù)庫(kù)的壓力?
2.1 消費(fèi)者數(shù)量少
此時(shí)應(yīng)該具體問(wèn)題具體分析了官研。消費(fèi)者數(shù)量太少秽澳,針對(duì)RabbitMQ來(lái)說(shuō),他提供了【RabbitMQ-2】RabbitMQ的并發(fā)參數(shù)(concurrency和prefetch)配置戏羽,可以設(shè)置核心的消費(fèi)者數(shù)量担神,和最大的消費(fèi)者數(shù)量,保證了在高峰期消費(fèi)者可以動(dòng)態(tài)擴(kuò)容蛛壳。
2.2 消費(fèi)者數(shù)量不少杏瞻,壓力在機(jī)器CPU或者內(nèi)存
水平擴(kuò)展消費(fèi)者集群即可所刀,畢竟機(jī)器成瓶頸了衙荐,增加幾個(gè)機(jī)器來(lái)消息不過(guò)分。
2.3 消費(fèi)者數(shù)量不少浮创,壓力在數(shù)據(jù)庫(kù)
此時(shí)忧吟,水平擴(kuò)展消費(fèi)者集群沒(méi)用了,需要和dba一起排查數(shù)據(jù)庫(kù)性能問(wèn)題的具體原因斩披,是消費(fèi)者中存在慢sql溜族;還是數(shù)據(jù)庫(kù)本身性能到極限,需要水平擴(kuò)展數(shù)據(jù)庫(kù)垦沉。
2.4 消費(fèi)者數(shù)量不少煌抒,壓力在接口
判斷接口數(shù)據(jù)能否被緩存,調(diào)用微服務(wù)接口的話厕倍,對(duì)壓力大的接口進(jìn)行優(yōu)化寡壮。
3. 線上出現(xiàn)消息堆積的事故
事故之所以是事故,那是因?yàn)榇a有bug了讹弯。
3.1 案例1—消息發(fā)送unack
首先說(shuō)下RabbitMQ消費(fèi)者的三種ACK機(jī)制:(1)無(wú)ACK(2)手動(dòng)ACK(3)自動(dòng)ACK
當(dāng)然線上項(xiàng)目况既,無(wú)ACK這種情況基本沒(méi)有。
- 自動(dòng)ACK:消息出現(xiàn)異常组民,并未捕獲交給Spring棒仍,那么會(huì)發(fā)送unack;
- 手動(dòng)ACK:消息在出現(xiàn)異常時(shí)臭胜,發(fā)送unack莫其;
無(wú)論哪種unack癞尚,消息都會(huì)重新回到隊(duì)列頭,然后這個(gè)消息會(huì)立即被推給消費(fèi)者乱陡。
你品否纬?這個(gè)消息在消費(fèi)者A出現(xiàn)異常,到達(dá)消費(fèi)者B大概率還是異常蛋褥,消息被重復(fù)的消費(fèi)-失敗-消費(fèi)...就會(huì)導(dǎo)致正常的消息不會(huì)被消費(fèi)临燃,造成消息堆積。
3.2 案例二—消息出現(xiàn)error異常
【RabbitMQ-13】驚烙心!線上的RabbitMQ消費(fèi)者自己kill自己膜廊,導(dǎo)致消息大量堆積
我們有一個(gè)隊(duì)列,由于某個(gè)消息過(guò)于巨大淫茵,導(dǎo)致了系統(tǒng)出現(xiàn)OOM爪瓜,消費(fèi)者出現(xiàn)了ERROR異常,然后消費(fèi)者掛了...關(guān)鍵這個(gè)消息又回到MQ中匙瘪,分發(fā)給下個(gè)消費(fèi)者铆铆,然后下個(gè)消息者也掛了...最后所有消費(fèi)者都掛了,消息瘋狂堆積丹喻。
4. 怎么處理線上的消息堆積事故
- 完善的監(jiān)控報(bào)警系統(tǒng):不能得到真正出現(xiàn)事故的時(shí)候薄货,開(kāi)發(fā)人員后知后覺(jué)。
- 快速定位代碼bug碍论,一般線上出現(xiàn)消息堆積谅猾,大概率是代碼問(wèn)題,快速修復(fù)代碼鳍悠,恢復(fù)消費(fèi)税娜;
- 根據(jù)實(shí)際的消息隊(duì)列,判斷是讓其自然消費(fèi)藏研,還是征用機(jī)器水平擴(kuò)展快速消費(fèi)敬矩;
5. 代碼中如何防止消息堆積
既然是事故,那么我們必須要防止事故蠢挡。
針對(duì)3種兩個(gè)案例:我說(shuō)下自己的解決方案:
5.1 消息unack導(dǎo)致消息堆積
消費(fèi)者不可避免出現(xiàn)異常弧岳,那么出現(xiàn)異常應(yīng)該如何處理呢?
【RabbitMQ-6】MQ中間件-rabbitmq-消費(fèi)者消息獲取及異常處理的實(shí)現(xiàn)(SpringBoot2.0環(huán)境下)
- 區(qū)分異常種類袒哥,判斷是否重回隊(duì)列缩筛;
- 設(shè)置消費(fèi)重回隊(duì)列的次數(shù),達(dá)到某個(gè)次數(shù)后堡称,不重回隊(duì)列瞎抛;
- 具體unack的消息是進(jìn)入死信隊(duì)列,還是記錄log表后丟棄却紧,需要看具體的業(yè)務(wù)桐臊;
5.2 消息出現(xiàn)ERROR異常
【RabbitMQ-13】驚胎撤!線上的RabbitMQ消費(fèi)者自己kill自己,導(dǎo)致消息大量堆積
里面記錄了兩種方法断凶。推薦提供一個(gè)自定義Advice對(duì)消費(fèi)者進(jìn)行AOP處理伤提。捕獲ERROR異常登記log表,不對(duì)Spring框架拋出ERROR異常认烁。