以前在寫Spring Cloud Stream專題內容的時候,特意介紹了一下如何使用RabbitMQ的延遲消息來實現定時任務。最近正好由於開發碰到了使用過程當中發現,延遲消息沒有效果,消息直接就被消費了的狀況。所以就繼續深刻研究了一下問題緣由,在此記錄下來,給碰到相似問題的童鞋們參考。java
由於不是全部的消息都出現了沒有延遲消息效果的因素,經過有問題的消息特徵,大體猜想多是延遲時間過長致使了消息延遲失敗。爲了驗證這個緣由,先拿以前文章中的例子,來測試一下延遲時間是否與問題直接相關。git
對以前的延遲消息使用樣例(文末的Git倉庫中能夠獲取完整代碼)接口作一下微改,增長了一個請求參數delay
來控制延遲時間:github
@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"; }
而後嘗試發起了兩個請求:spring
請求1:延遲5000毫秒。消息發送到MQ以後確實延遲了5秒以後才獲得了消費,沒有任何問題。app
curl localhost:8080/sendMessage?message=hello&delay=5000
請求2:延遲1年(31536000000毫秒)。消息發送到MQ以後立刻就被消費者消費了,徹底沒有延遲效果。curl
curl localhost:8080/sendMessage?message=hello&delay=31536000000
在明確了問題緣由以後,須要對該功能的時候作一些明確的限定(延遲時間的極限),以免再次出現相似的問題。深刻探索下去,這裏的失敗主要與消息的過時時間(TTL)有直接的關係。在RabbitMQ中,消息的過時時間必須是非負 32 位整數,即:0 <= n <= 2^32-1,以毫秒爲單位。 其中,2^32-1 = 4294967295。測試
這裏咱們能夠嘗試下面兩個請求,分別設置延遲時間爲4294967295何4294967296:ui
curl localhost:8080/sendMessage?message=hello&delay=4294967295 curl localhost:8080/sendMessage?message=hello&delay=4294967296
能夠發現,當延遲時間爲4294967295毫秒的時候,延遲消息工做正常;當延遲時間爲4294967296毫秒的時候,消息被直接消費,沒有延遲效果。url
因此,咱們在使用RabbitMQ的延遲消息功能時候,必須注意它的延遲極限是4294967295毫秒。若是你的業務需求會超過這個臨界值,就必須避開這個坑,採用其餘方法來實現須要延遲或者定時執行的任務了。spa
本文示例讀者能夠經過查看下面倉庫的中的stream-delayed-message項目:
若是您對這些感興趣,歡迎star、follow、收藏、轉發給予支持!