相關知識
交換器
- direct:一對一
- fanout:一對多
- topic:模式匹配
目標
整合 Spring boot 提供的 spring-boot-starter-amqp,實現消息發送、消息消費、確認
準備工作
安裝RabbitMQ
請自行根據windows或者Linux進行安裝
操作步驟
添加依賴
添加後的整體依賴如下
配置
編碼(消息發送方)
定義 Exchange、Queue並將兩者進行關聯
Controller 層代碼
引入 spring-boot-starter-amqp 時,會自動註冊 RabbitTemplate 到 Spring 容器,
消息發送可以藉助其提供的 convertAndSend 方法
啓動類
編碼(消息消費方)
定義 Queue
定義消費類
- 在類上使用註解 @RabbitListener,聲明監聽的隊列
- 在處理方法上使用註解 @RabbitHandler,標記該方法爲回調處理方法
啓動類
測試消費消息
使用 Application 類啓動項目,在日誌中可以看到消費消息時產生的日誌
DirectReceiver消費者收到消息 : {msgId=ccf1f1c0-f8c5-483a-933e-ed3d77d59333, msgData=null, sendTime=2020-01-07 19:50:23}
去 RabbitMQ 管理後臺,查看 Queues 標籤頁,可以看到隊列 TestDirectQueue 的 Ready 值變成了 0,表示消息已經被消費。
編碼(消息消費方實現消息確認)
消息接收的確認機制主要存在三種模式:
- 自動確認,默認值,RabbitMQ 將消息發送給應用程序,即認爲消費成功,如果應用程序在消費消息的過程中,發生異常,RabbitMQ 是無法感知的,依然會將該消息從隊列中刪除,但實際上應用程序又沒有消費成功,相當於丟失了消息。
- 不確認,忽略
- 手動確認,實際生產多數選擇的模式,應用程序接收到消息並進行處理後,返回一個響應(ACK),RabbitMQ 接收到這個響應後,判斷是消費成功,還是失敗,並調用相應的回調方法進行處理。
- basic.ack 用於肯定確認
- basic.nack 用於否定確認
- basic.reject 用於否定確認,但與 basic.nack 相比有一個限制,一次只能拒絕單條消息
配置
設置消息消費 ACK 模式爲自動模式
定義消費類
basicReject 的第二個參數是 requeue,意思是是否重新加入隊列,
如果爲 true,則表示本次消費不成功,並將當前消息重新加入至當前隊列,
如果爲 false,則表示本次消費不成功,並將當前消息丟棄,如果有設置死信隊列,則會進入死信隊列(關於死信隊列,在下一章會講)
源碼地址
本章源碼 :https://github.com/caiyuanzi-song/boot.git
結束語
消息隊列是實際生產中是必備組件,用於保證系統高可用、高性能、可擴展
- 解耦:類比觀察者模式,比如用戶註冊成功後,需要記錄日誌、發送短信,原始操作就是在用戶註冊成功後,分別調用記錄日誌及發送短信的方法,使用消息隊列後,則可以在用戶註冊成功後,發送一個註冊成功的消息,而註冊成功的後續操作則可以訂閱該消息隊列,分別實現各自的處理邏輯。如果業務變更,增加了新業務,則不用修改原來的代碼,而只需要增加一個訂閱即可。
- 異步:用戶註冊成功後需要發送短信,而發送短信是一個非常耗時的操作,這不僅會影響到用戶體驗,因爲短信發送過程中,程序長時間阻塞,還可能造成後臺資源緊張。使用消息隊列,異步處理短信發送,則可以完美解決這個問題。這個保證系統高性能的一種常用手段。
- 削峯/限流:用戶註冊成功後需要發送短信,而發送短信是一個非常耗時的操作,如果此時有大量請求請求該接口,可能會導致系統掛掉。使用消息隊列,異步進行處理,則可以避免這個問題,如果流量特別大,異步一個一個處理都會導致系統宕機,還可以限流,在發送消息時先檢測隊列是否已滿,如果已滿,則直接給前端返回錯誤。
擴展
發送 Fanout 消息
定義隊列
Fanout 交換器沒有 Routing,直接將隊列與交換器進行關聯即可
發送方法
也是調用 convertAndSend 方法,只是 routing 參數傳值 null
發送 Topic 消息
定義隊列
發送方法
跟使用 direct 交換器一樣,只是 topic 交互器會根據 routing 進行匹配,然後決定將消息發送至哪些隊列