RabbitMQ(一) -- 消息發送、消費、確認與持久化

一:風騷概述

消息隊列中間件有衆多產品系列,當前主流就RabbitMQ和Kafka。本系列將不會涉及隊列中間件技術選型,而是將由淺入深開始RabbitMQ的旅程。作爲開篇第一章將會介紹Java中如何向RabbitMQ發送消息、消費消息、消息隊列持久化、公平派遣消費、消息確認機制、消息預存取等內容

二:準備工作

RabbitMQ服務將使用官方維護的一個Docker鏡像部署,其餘安裝方式其移步官網查閱。客戶端使用Springboot2.1.6RELEASE集成並編寫相關Demo

2.1 Docker鏡像部署服務

更多docker的知識後續會更新博客,目前爲了研究RabbitMQ相關知識只是簡單運用別人製作的鏡像部署。按照下面的命令執行即可,執行確認完畢後訪問http://ip:15672即可查看管理RabbitMQ,賬號密碼默認都是guest

// 拉取鏡像,不帶management的鏡像沒有管理界面
docker pull rabbitmq:management
// 查看鏡像是否下載成功
docker images
// 製作容器
docker create rabbitmq:management
// 查看容器是否製作成功
docker ps -a
// 啓動容器並映射端口
docker run -d --name rabbitmq -p 15672:15672 -p 5672:5672 rabbitmq:management
// 查看容器是否運行
docker ps 
2.2 客戶端依賴引入

因爲本文建立在SpringBoot的基礎上,所以只需要引入如下依賴即可

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

三:簡單消息發送與消費

稍微有點隊列中間件基礎的同學可能對於各種路由、交換、分區概念不會陌生,但是本文僅僅是開篇第一章,所以接下來的行文不會涉及到上述概念。使用RabbitMQ的默認隊列完成入門Demo效果測試即可

3.1 消息發送

在這裏插入圖片描述
消息發送在不考慮各種異常處理、隊列持久化、消息持久化、路由規則等情況下如上圖所示比較簡單,截圖中代碼註釋也是比較詳細。接下來重點提出介紹以下幾點:

  • ip端口默認:localhost:5672,部署在本地且未更改端口可以不用設置對應屬性
  • 賬號密碼:默認guest,若未更改賬號密碼可以不用設置對應屬性
  • Connection:連接已實現Closeable,可使用try-with-resource處理自動關閉
  • Channel:通道已實現Closeable,可使用try-with-resource處理自動關閉

在這裏插入圖片描述

3.2 消息消費

在這裏插入圖片描述
消息消費着重點在於DeliverCallback,這個函數式接口實現消息消費的邏輯結構。當然就像註釋中說的一樣,消費端創建隊列的目的在於避免生產端爲啓動沒有隊列而引發異常
在這裏插入圖片描述

四:消息預取

隊列中堆積成千上萬條消息,一下全部推送給消費者?如果在某些情況下消息內存佔用較大你的消費端直接就沒了吧

4.1 消費者限流

限制每次隊列推送消息數量是十分必要的,可以根據消費能力與隊列消息累積速度適當把控調整。實現代碼就如下一行即可,當然這個設定將會限制通道上所有消費者單次預取數爲1

  // 消費端限流
  channel.basicQos(1);
4.2 通道限流

若想讓某通道上所有消費者的預取數相加結果爲參數指定數量可行麼?basicQos()有如下重載,除了第一個參數限定預取消息數量之外第二個參數用於指定這個限流是針對單消費者還是通道

  • false:默認值,非全局即單個消費者每次預取消息數量
  • true:全局即通道上所有消費者累計預取消息數量

在這裏插入圖片描述

五:消息確認

簡單消息消費模塊中所有消息在消費端預取後將立即在隊列中刪除,若因爲後續邏輯異常將導致所有消息丟失。這是災難性的一個事情,消息確認機制就是用於消費端手動控制刪除隊列中的消息

5.1 basicAck

basicConsume()方法第二個參數autoAck,顧名思義就能知道有何意義。簡單消息消費中這個參數被設置爲true即獲取消息後就刪除。若想實現手動確認刪除將該參數設置爲false
在這裏插入圖片描述
設置爲手
動確認後如果消費者在爲返回確認標誌ack前異常亦或是宕機,該消息會重新放回隊列由其餘消費者完成消費。確認動作如下所示,可以消費方法中執行完畢後設定
在這裏插入圖片描述
假設預取了100條消息,消費完一條後就需要對RabbitMQ服務器發送一條確認指令,影響將會是增加了網絡消耗。所以basicAck()第二個參數用於指定是否確認所有未確認消息,當然前提是消息對應的deliveryTag小於本次確認提交消息對應的deliveryTag

5.2 basicReject

與basicAck()確認消息相反的是basicReject(),拒絕確認消息。調用該方法如下圖所示,第一個參數爲消息對應deliveryTag,第二個參數就表示是否將拒絕確認的消息重新放回隊列排隊
在這裏插入圖片描述
在這裏插入圖片描述

5.3 basicNack

相對於basicReject來講basicNack就是優化了批量提交確認,第二個參數含義爲是否批量提交確認,效果與basicAck的批量提交確認一致。其餘參數含義則與basicReject一致
在這裏插入圖片描述

六:持久化

消息隊列中的消息當MQ服務宕機以後會被清理,這是一個恐怖的故事。接下來情節的繼續就是講解如何將消息進行持久化的操作

6.1 隊列Queue

隊列持久化保證MQ服務宕機後隊列不會被刪除,具體操作爲在創建隊列的時候將第二個參數durable設置爲true即可。控制檯體現爲Features屬性中有D,表示該隊列被持久化。但是需要注意的就是隊列持久化並不能保證隊列中消息的持久化
在這裏插入圖片描述
在這裏插入圖片描述

6.2 消息持久化

將對俄設置爲持久化隊列後需要再設置隊列中消息的持久化,操作就是在發送消息的時候將第三個參數設置爲MessageProperties.PERSISTENT_TEXT_PLAIN,表示消息的持久化。但是注意消息持久化也就是將消息寫入磁盤,這樣帶來的性能消耗需要引起足夠的重視
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章