最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

簡單聊聊RabbitMQ中的隊頭阻塞問題

 更新時間:2025年02月19日 08:14:28   作者:Java中文社群  
這篇文章主要為大家詳細介紹了RabbitMQ中的隊頭阻塞問題以及相關(guān)的解決方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

RabbitMQ 延遲消息的隊頭阻塞問題是指,在使用死信隊列(DLX)和 TTL(消息過期時間)實現(xiàn)延遲消息時,由于隊列的先進先出(FIFO)特性,在隊列頭部消息未過期的情況下,即使后續(xù)消息已經(jīng)過期也不能及時處理的情況。

實現(xiàn)原理

RabbitMQ 延遲消息的實現(xiàn)方式有以下兩種:

  • 死信隊列+TTL
  • 使用 rabbitmq-delayed-message-exchange 插件。

而我們本文要討論的“RabbitMQ 延遲消息的隊頭阻塞問題”只會發(fā)生在死信隊列+TTL 的實現(xiàn)方式中。

死信隊列 + TTL 的實現(xiàn)流程如下:

  • 生產(chǎn)者先將設(shè)置了 TTL(過期時間)的消息發(fā)送到普通隊列。
  • 普通隊列沒有消息者,所以一定會過期,消息過期之后就會發(fā)送到死信隊列。
  • 消費者訂閱死信隊列獲取消息,并執(zhí)行延遲任務(wù)。

代碼實現(xiàn)

死信隊列 + TTL 在 Spring Boot 項目中的實現(xiàn)代碼如下。

定義死信交換器(DLX)和死信隊列

// Spring Boot 配置示例
@Configuration
public class RabbitConfig {
    // 定義死信交換器
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange("dlx.exchange");
    }

    // 定義死信隊列
    @Bean
    public Queue dlxQueue() {
        return new Queue("dlx.queue");
    }

    // 綁定死信隊列到 DLX
    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with("dlx.routing.key");
    }

    // 定義普通隊列,設(shè)置死信交換器和路由鍵
    @Bean
    public Queue mainQueue() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", "dlx.exchange");
        args.put("x-dead-letter-routing-key", "dlx.routing.key");
        // 可選:設(shè)置隊列級別的 TTL(所有消息統(tǒng)一過期時間)
        args.put("x-message-ttl", 10000); // 10秒
        return new Queue("main.queue", true, false, false, args);
    }

    // 主隊列綁定到默認交換器(根據(jù)需要調(diào)整)
    @Bean
    public Binding mainBinding() {
        return BindingBuilder.bind(mainQueue()).to(new DirectExchange("default.exchange")).with("main.routing.key");
    }
}

發(fā)送消息時設(shè)置 TTL(消息級別)

// 發(fā)送延遲消息(消息級別 TTL)
public void sendDelayedMessage(String message, int delayMs) {
    rabbitTemplate.convertAndSend("default.exchange", "main.routing.key", message, msg -> {
        // 設(shè)置消息過期時間(覆蓋隊列級別的 TTL)
        msg.getMessageProperties().setExpiration(String.valueOf(delayMs));
        return msg;
    });
}

消費者監(jiān)聽死信隊列

@RabbitListener(queues = "dlx.queue")
public void handleDelayedMessage(String message) {
System.out.println("處理延遲消息: " + message);
}

所以說消息的過期時間 TTL 的設(shè)置方式有以下兩種:

隊列級別:通過設(shè)置隊列的 x-message-ttl 參數(shù),設(shè)置隊列統(tǒng)一的過期時間。

Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", 60000); // 設(shè)置隊列消息過期時間為 60 秒
channel.queueDeclare(queueName, true, false, false, args);

消息級別:通過給每個消息設(shè)置 expiration 屬性,為每個消息設(shè)置過期時間。

AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
        .deliveryMode(2) // 消息持久化
        .expiration("60000") // 設(shè)置消息過期時間為 60 秒
        .build();
channel.basicPublish(exchangeName, routingKey, properties, message.getBytes());

如果同時設(shè)置了消息級 TTL 和隊列級 TTL,消息的實際過期時間會取兩者中的最小值。

造成隊頭阻塞的原因

造成隊頭阻塞的原因有以下兩個:

  • 先進先出的隊列特性:隊列中的消息必須按順序處理,即使后面的消息 TTL 較短且已過期,也必須等待隊頭的消息先被處理(或過期)。
  • TTL 檢查機制:RabbitMQ 默認僅在處理隊頭消息時檢查其 TTL,如果隊頭消息的 TTL 較長(例如 10 分鐘),即使后續(xù)消息的 TTL 更短(例如 1 分鐘),這些消息也會被阻塞,直到隊頭消息過期或被移除。

如下圖所示:

解決方案

  • 為不同延遲時間創(chuàng)建獨立隊列:將相同 TTL 的消息放入同一隊列,避免消息的過期時間不一致。
  • 使用延遲插件:使用 RabbitMQ 的延遲插件 rabbitmq_delayed_message_exchange,直接通過延遲交換機實現(xiàn)延遲消息,繞過死信隊列的 FIFO 限制。延遲插件是通過將消息存儲到內(nèi)置數(shù)據(jù)庫 Mnesia,再通過不斷判斷過期消息,實現(xiàn)延遲消息的投遞和執(zhí)行的,因此它不存在隊列的先進先出和隊頭阻塞的問題。

小結(jié)

隊頭阻塞問題是發(fā)生在使用死信隊列加 TTL 實現(xiàn) RabbitMQ 延遲消息的場景中,造成的原因是隊列先進先出的特性,加上延遲消息的檢查機制導(dǎo)致的,我們可以使用 RabbitMQ 的延遲插件來避免此問題。

那么問題來了,使用延遲插件如何實現(xiàn)延遲任務(wù)?它和死信隊列的實現(xiàn)方式有哪些具體的區(qū)別呢?

到此這篇關(guān)于簡單聊聊RabbitMQ中的隊頭阻塞問題的文章就介紹到這了,更多相關(guān)RabbitMQ隊頭阻塞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • idea中@Autowired注解下變量報紅的解決

    idea中@Autowired注解下變量報紅的解決

    這篇文章主要介紹了idea中@Autowired注解下變量報紅的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中Elasticsearch的4種分頁方式詳解

    Java中Elasticsearch的4種分頁方式詳解

    在?Elasticsearch?中,有?4種常見的分頁方法,本文將帶大家分析一下每種方法的優(yōu)缺點以及我們該如何選擇,感興趣的小伙伴可以參考一下
    2025-01-01
  • Java詳解swagger2如何配置使用

    Java詳解swagger2如何配置使用

    編寫和維護接口文檔是每個程序員的職責(zé),根據(jù)Swagger2可以快速幫助我們編寫最新的API接口文檔,再也不用擔(dān)心開會前仍忙于整理各種資料了,間接提升了團隊開發(fā)的溝通效率
    2022-06-06
  • Java中的volatile實現(xiàn)機制詳細解析

    Java中的volatile實現(xiàn)機制詳細解析

    這篇文章主要介紹了Java中的volatile實現(xiàn)機制詳細解析,本文的主要內(nèi)容就在于要理解volatile的緩存的一致性協(xié)議導(dǎo)致的共享變量可見性,以及volatile在解析成為匯編語言的時候?qū)ψ兞考渔i兩塊理論內(nèi)容,需要的朋友可以參考下
    2024-01-01
  • Java的MyBatis框架項目搭建與hellow world示例

    Java的MyBatis框架項目搭建與hellow world示例

    MyBatis框架為Java程序的數(shù)據(jù)庫操作帶來了很大的便利,這里我們就從最基礎(chǔ)的入手,來看一下Java的MyBatis框架項目搭建與hellow world示例,需要的朋友可以參考下
    2016-06-06
  • Java操作XML轉(zhuǎn)JSON數(shù)據(jù)格式詳細代碼實例

    Java操作XML轉(zhuǎn)JSON數(shù)據(jù)格式詳細代碼實例

    在Java中我們可以使用一些現(xiàn)成的庫來實現(xiàn)XML到JSON的轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于Java操作XML轉(zhuǎn)JSON數(shù)據(jù)格式的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-04-04
  • java非遞歸實現(xiàn)之二叉樹的前中后序遍歷詳解

    java非遞歸實現(xiàn)之二叉樹的前中后序遍歷詳解

    樹的遍歷順序大體分為三種:前序遍歷(先根遍歷、先序遍歷),中序遍歷(中根遍歷),后序遍歷(后根遍歷),本文將給大家詳細的介紹,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值
    2021-09-09
  • Maven下載依賴的順序及配置文件小結(jié)

    Maven下載依賴的順序及配置文件小結(jié)

    本文主要介紹了Maven下載依賴的順序及配置文件小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • 在Java下利用log4j記錄日志的方法

    在Java下利用log4j記錄日志的方法

    本文先對log4j進行了簡短的介紹,而后通過安裝、配置和普通項目和web項目幾個方面來詳細介紹了在Java下利用log4j記錄日志的方法,有需要的朋友們可以參考借鑒。
    2016-09-09
  • Java中的異步與線程池解讀

    Java中的異步與線程池解讀

    這篇文章主要介紹了Java中的異步與線程池,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評論

三明市| 东港市| 常山县| 尉犁县| 永靖县| 天镇县| 醴陵市| 拜城县| 内黄县| 临漳县| 武定县| 梧州市| 陇南市| 理塘县| 宁安市| 大洼县| 读书| 阿鲁科尔沁旗| 惠安县| 荥经县| 南开区| 宝清县| 奎屯市| 清水河县| 普格县| 清原| 莱西市| 九江市| 土默特左旗| 即墨市| 彩票| 长春市| 长宁县| 宁化县| 彭水| 邳州市| 天长市| 丹江口市| 阜平县| 肃北| 元氏县|