設(shè)計(jì)
重試數(shù)次后孕惜,轉(zhuǎn)發(fā)到無(wú)法處理的隊(duì)列(后面稱(chēng)之為兜底隊(duì)列)中驶睦,示意圖如下:
消息-->隊(duì)列1-->失敗-->隊(duì)列1(數(shù)次)-->達(dá)到上限-->兜底隊(duì)列
我由于自定義了SimpleRabbitListenerContainerFactory
的Bean,因此spring中對(duì)于listener.simple.retry的設(shè)置統(tǒng)統(tǒng)不起作用蒸播,干脆全在這里面實(shí)現(xiàn)睡榆,也更加客制化萍肆。
要點(diǎn)
- 設(shè)置好重試的各個(gè)參數(shù)
包括但不限于:最大重試次數(shù)、初始重試間隔時(shí)間胀屿、間隔時(shí)間增長(zhǎng)數(shù)塘揣、最大間隔時(shí)間
寫(xiě)成代碼就這樣:
// SimpleRabbitListenerContainerFactory
factory.setAdviceChain(org.springframework.amqp.rabbit.config.RetryInterceptorBuilder
.stateless()
.maxAttempts(5) // 最大重試次數(shù)
.backOffOptions(1000, 2, 15000) // 初始間隔時(shí)間、間隔時(shí)間增長(zhǎng)數(shù)宿崭、最大間隔時(shí)間(單位都是毫秒)
.build());
- 設(shè)置上兜底策略
這個(gè)叫法是我起的亲铡,大佬們有專(zhuān)業(yè)名詞麻煩指正下,謝謝葡兑。
其實(shí)就是達(dá)到重試的上限次數(shù)后的操作奖蔓,我選用設(shè)置recoverer進(jìn)行操作,當(dāng)達(dá)到上限之后铁孵、或者被拋出AmqpRejectAndDontRequeueException
后,都會(huì)觸發(fā)recoverer的recover方法房资。而且蜕劝,AMQP還提供了一個(gè)RepublishMessageRecoverer
可供使用,它在觸發(fā)使用后會(huì)進(jìn)行轉(zhuǎn)發(fā)轰异,轉(zhuǎn)發(fā)的exchange和routekey可以在new的時(shí)候定義清楚岖沛。
如下所示
RepublishMessageRecoverer recoverer = new RepublishMessageRecoverer(rabbitTemplate,
getExchange(),
getRouteKey());
factory.setAdviceChain(org.springframework.amqp.rabbit.config.RetryInterceptorBuilder
.recoverer(recoverer)
.build());
這樣就可以了,但是有兩個(gè)問(wèn)題搭独,
- 如果兜底隊(duì)列處理時(shí)再出問(wèn)題怎么辦婴削?暫時(shí)沒(méi)好辦法,它會(huì)不停地被扔兜底隊(duì)列中牙肝,但由于有等待唉俗,cpu消耗還是比沒(méi)有的好很多
- 兜底隊(duì)列該如何處理里面的消息?一種辦法是直接打印成特殊的日志消費(fèi)掉配椭,后面人工查看日志并制定解決方案
其他
之前找解決方案時(shí)老是找到“死信隊(duì)列”上虫溜,但如你所見(jiàn),這里并沒(méi)有用到死信股缸,而且很多博文總是把死信和ttl結(jié)合起來(lái)衡楞,明明死信的來(lái)源不止一個(gè)……但說(shuō)回來(lái),即使綁了死信隊(duì)列敦姻,我重試遠(yuǎn)超上限后仍沒(méi)有發(fā)往死信隊(duì)列瘾境,可能也是我提供了自定義的SimpleRabbitListenerContainerFactory
有關(guān),由于時(shí)間關(guān)系沒(méi)有嘗試镰惦,有哪位大佬試過(guò)了歡迎分享和指正迷守。