摘要:?jiǎn)栴}定位因?yàn)椴皇撬械南⒍汲霈F(xiàn)了沒(méi)有延遲消息效果的因素,通過(guò)有問(wèn)題的消息特征,大致猜測(cè)可能是延遲時(shí)間過(guò)長(zhǎng)導(dǎo)致了消息延遲失敗。所以,我們?cè)谑褂玫难舆t消息功能時(shí)候,必須注意它的延遲極限是毫秒。
之前在寫(xiě)Spring Cloud Stream專題內(nèi)容的時(shí)候,特地介紹了一下如何使用RabbitMQ的延遲消息來(lái)實(shí)現(xiàn)定時(shí)任務(wù)。最近正好因?yàn)殚_(kāi)發(fā)碰到了使用過(guò)程中發(fā)現(xiàn),延遲消息沒(méi)有效果,消息直接就被消費(fèi)了的情況。因此就繼續(xù)深入研究了一下問(wèn)題原因,在此記錄下來(lái),給碰到類似問(wèn)題的童鞋們參考。
問(wèn)題定位因?yàn)椴皇撬械南⒍汲霈F(xiàn)了沒(méi)有延遲消息效果的因素,通過(guò)有問(wèn)題的消息特征,大致猜測(cè)可能是延遲時(shí)間過(guò)長(zhǎng)導(dǎo)致了消息延遲失敗。為了驗(yàn)證這個(gè)原因,先拿之前文章中的例子,來(lái)測(cè)試一下延遲時(shí)間是否與問(wèn)題直接相關(guān)。
對(duì)之前的延遲消息使用樣例(文末的Git倉(cāng)庫(kù)中可以獲取完整代碼)接口做一下微改,增加了一個(gè)請(qǐng)求參數(shù)delay來(lái)控制延遲時(shí)間:
@GetMapping("/sendMessage") public String messageWithMQ(@RequestParam String message, @RequestParam Long delay) { log.info("Send: " + message); testTopic.output().send(MessageBuilder.withPayload(message).setHeader("x-delay", delay).build()); return "ok"; }
然后嘗試發(fā)起了兩個(gè)請(qǐng)求:
請(qǐng)求1:延遲5000毫秒。消息發(fā)送到MQ之后確實(shí)延遲了5秒之后才得到了消費(fèi),沒(méi)有任何問(wèn)題。
curl localhost:8080/sendMessage?message=hello&delay=5000
請(qǐng)求2:延遲1年(31536000000毫秒)。消息發(fā)送到MQ之后馬上就被消費(fèi)者消費(fèi)了,完全沒(méi)有延遲效果。
curl localhost:8080/sendMessage?message=hello&delay=31536000000問(wèn)題小結(jié)
在明確了問(wèn)題原因之后,需要對(duì)該功能的時(shí)候做一些明確的限定(延遲時(shí)間的極限),以避免再次出現(xiàn)類似的問(wèn)題。深入探索下去,這里的失敗主要與消息的過(guò)期時(shí)間(TTL)有直接的關(guān)系。在RabbitMQ中,消息的過(guò)期時(shí)間必須是非負(fù) 32 位整數(shù),即:0 <= n <= 2^32-1,以毫秒為單位。 其中,2^32-1 = 4294967295。
這里我們可以嘗試下面兩個(gè)請(qǐng)求,分別設(shè)置延遲時(shí)間為4294967295何4294967296:
curl localhost:8080/sendMessage?message=hello&delay=4294967295 curl localhost:8080/sendMessage?message=hello&delay=4294967296
可以發(fā)現(xiàn),當(dāng)延遲時(shí)間為4294967295毫秒的時(shí)候,延遲消息工作正常;當(dāng)延遲時(shí)間為4294967296毫秒的時(shí)候,消息被直接消費(fèi),沒(méi)有延遲效果。
所以,我們?cè)谑褂肦abbitMQ的延遲消息功能時(shí)候,必須注意它的延遲極限是4294967295毫秒。如果你的業(yè)務(wù)需求會(huì)超過(guò)這個(gè)臨界值,就必須避開(kāi)這個(gè)坑,采用其他方法來(lái)實(shí)現(xiàn)需要延遲或者定時(shí)執(zhí)行的任務(wù)了。
代碼示例本文示例讀者可以通過(guò)查看下面?zhèn)}庫(kù)的中的stream-delayed-message項(xiàng)目:
Github: https://github.com/dyc87112/S...
Gitee: https://gitee.com/didispace/S...
如果您對(duì)這些感興趣,歡迎star、follow、收藏、轉(zhuǎn)發(fā)給予支持!
歡迎關(guān)注我的公眾號(hào):程序猿DD,獲得獨(dú)家整理的學(xué)習(xí)資源和日常干貨推送。如果您對(duì)我的專題內(nèi)容感興趣,也可以關(guān)注我的博客:didispace.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/75551.html
摘要:然而實(shí)際業(yè)務(wù)中還存在另外一種定時(shí)任務(wù),它可能需要一些觸發(fā)條件才開(kāi)始定時(shí),比如編寫(xiě)博文時(shí)候,設(shè)置小時(shí)之后發(fā)送。在消息監(jiān)聽(tīng)類中,對(duì)通道定義了,這里會(huì)對(duì)延遲消息做具體的邏輯。由于消息的消費(fèi)是延遲的,從而變相實(shí)現(xiàn)了從消息發(fā)送那一刻起開(kāi)始的定時(shí)任務(wù)。 應(yīng)用場(chǎng)景 我們?cè)谑褂靡恍╅_(kāi)源調(diào)度系統(tǒng)(比如:elastic-job等)的時(shí)候,對(duì)于任務(wù)的執(zhí)行時(shí)間通常都是有規(guī)律性的,可能是每隔半小時(shí)執(zhí)行一次,或者...
摘要:官方插件僅支持版本中支持。使用過(guò)程聲明消息交換機(jī)實(shí)現(xiàn)實(shí)現(xiàn)消息發(fā)送實(shí)現(xiàn)實(shí)現(xiàn) 官方插件僅支持>=3.6.x 版本中支持。 本文描述的消息延遲機(jī)制采用官方推薦的插件rabbitmq-delayed-message-exchange,如精通rabbitmq和編程,請(qǐng)自行查看官方文檔,描述更加詳盡: github Rabbitmq插件列表 安裝 需要在集群每臺(tái)機(jī)器中安裝由于rabbitmq并...
摘要:另一種就是用中的位于包下,本質(zhì)是由和實(shí)現(xiàn)的阻塞優(yōu)先級(jí)隊(duì)列。表明了一條消息可在隊(duì)列中存活的最大時(shí)間。當(dāng)某條消息被設(shè)置了或者當(dāng)某條消息進(jìn)入了設(shè)置了的隊(duì)列時(shí),這條消息會(huì)在時(shí)間后死亡成為。 SpringBoot 是為了簡(jiǎn)化 Spring 應(yīng)用的創(chuàng)建、運(yùn)行、調(diào)試、部署等一系列問(wèn)題而誕生的產(chǎn)物,自動(dòng)裝配的特性讓我們可以更好的關(guān)注業(yè)務(wù)本身而不是外部的XML配置,我們只需遵循規(guī)范,引入相關(guān)的依賴就可...
摘要:基礎(chǔ)組件架構(gòu)設(shè)計(jì)基礎(chǔ)組件封裝設(shè)計(jì)迅速消息發(fā)送支持迅速消息發(fā)送模式,在一些日志收集統(tǒng)計(jì)分析等需求下可以保證高性能,高吞吐量?;A(chǔ)組件封裝設(shè)計(jì)事務(wù)消息發(fā)送支持事務(wù)消息,且保障可靠性投遞,在金融行業(yè)單筆大金額操作時(shí)會(huì)有此類需求。 Rabbitmq基礎(chǔ)組件架構(gòu)設(shè)計(jì) 基礎(chǔ)組件封裝設(shè)計(jì) - 迅速消息發(fā)送支持迅速消息發(fā)送模式,在一些日志收集、統(tǒng)計(jì)分析等需求下可以保證高性能,高吞吐量。 基礎(chǔ)組件封...
閱讀 3459·2023-04-25 17:19
閱讀 719·2021-11-23 09:51
閱讀 1427·2021-11-08 13:19
閱讀 881·2021-09-29 09:34
閱讀 1782·2021-09-28 09:36
閱讀 1572·2021-09-22 14:59
閱讀 2799·2019-08-29 16:38
閱讀 2134·2019-08-26 13:40