Spring Boot RabbitMQ 應用場景
1. 前言
消息隊列是一個容器,可以對程序產生的消息進行存儲。消息隊列的主要用途是削峰、異步、解耦,我們用一個實際場景來解釋下。
有一家果汁生產企業,張三是采購員,負責采購水果;李四、趙五是配送員,分別負責將蘋果、香蕉配送到生產車間。
1.1 削峰
傳統模式下,張三采購完成,回到公司后,聯系李四、趙五配送采購的水果。但是隨著公司業務量大增,張三一次性采購的水果,李四、趙五得需要幾天才能配送完。所以需要一個倉庫,張三采購完成直接放到倉庫里,李四、趙五慢慢從倉庫取出配送。
此處的倉庫就是消息隊列,張三是采購消息的生產者,李四、趙五是消費者。當生產的消息太多時,可以使用隊列削峰
,這樣消費者可以慢慢處理消息。
1.2 異步
傳統模式下,張三采購完成后,需要等待李四、趙五來取,實際上極大浪費了張三的時間。如果直接放入倉庫,可以不必等待,直接進行下面的工作。也就是說,張三與李四、趙五的工作是異步
的,減少了等待時間。
1.3 解耦
之前張三采購完成后,有責任通知李四、趙五來取。萬一李四、趙五忘帶手機,張三還得聯系領導協調處理,說實話張三就是個大老粗,整天為這些破事煩得不行。
如果直接放入倉庫,張三根本不用管李四、趙五的事情,感覺愉快極了。張三與李四、趙五的工作不再互相依賴,都變得更加簡單了,這就是解耦
。
2. RabbitMQ 簡介
RabbitMQ 是非常出名的消息中間件,遵循 AMQP 協議,可以跨平臺、跨語言使用。 RabbitMQ 具備低時延、高可用的特點,還有簡潔易用的可視化管理界面,所以本節我們使用 RabbitMQ 來進行消息隊列技術的演示。
3. Spring Boot 實現
我們就針對上面的場景,使用 Spring Boot ,結合 RabbitMQ 來具體實現下水果采購、配送的管理。
3.1 使用 Spring Initializr 創建項目
Spring Boot 版本選擇 2.2.5 ,Group 為 com.imooc , Artifact 為 spring-boot-rabbitmq,生成項目后導入 Eclipse 開發環境。
3.2 引入項目依賴
我們引入 Web 項目依賴與 AMQP 消息隊列依賴。
實例:
<!-- Web 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- AMQP 依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3.3 配置 RabbitMQ 連接信息
項目創建后,通過 applicaiton.properties 配置 RabbitMQ 的鏈接信息。
實例:
#地址
spring.rabbitmq.host=127.0.0.1
#端口 默認5672
spring.rabbitmq.port=5672
#用戶名
spring.rabbitmq.username=guest
#密碼
sprng.rabbitmq.password=guest
3.4 配置隊列
首先配置兩個隊列,存儲蘋果采購消息、香蕉采購消息。
實例:
/**
* 消息隊列配置類
*/
@Configuration
public class RabbitConfig {
/**
* 蘋果采購消息隊列
*/
@Bean
public Queue appleQueue() {
return new Queue("apple-queue");
}
/**
* 香蕉采購消息隊列
*/
@Bean
public Queue bananaQueue() {
return new Queue("banana-queue");
}
}
3.5 配置交換機和綁定
如果消息直接發到隊列的話,不夠靈活, RabbitMQ 提供了交換機與綁定機制。
消息發送給交換機,交換機可以靈活地與隊列進行綁定,這樣消息就可以通過多種方式進入隊列了。
實例:
/**
* 配置交換機
*/
@Bean
TopicExchange exchangeTopic() {
return new TopicExchange("exchange-topic");
}
/**
* 交換機綁定蘋果采購消息隊列
*/
@Bean
Binding bindAppleQueue() {
return BindingBuilder.bind(appleQueue()).to(exchangeTopic()).with("#.apple.#");
}
/**
* 交換機綁定香蕉采購消息隊列
*/
@Bean
Binding bindBananaQueue() {
return BindingBuilder.bind(bananaQueue()).to(exchangeTopic()).with("#.banana.#");
}
我們來詳細解釋下交換機與綁定的運行機制。
- 我們配置了一個交換機 exchangeTopic ,它可以接收消息。
- 交換機 exchangeTopic 綁定了兩個隊列,分別是 appleQueue 和 bananaQueue ,說明這兩個隊列在關注該交換機收到的消息。
- 那么交換機 exchangeTopic 收到的消息到底會進入哪個隊列呢,我們發現交換機的類型是
TopicExchange
,說明該交換機是話題
交換機,隊列應該是獲取其感興趣的話題相關的消息。 - 當 appleQueue 隊列綁定到交換機時,
with("#.apple.#")
就表示 appleQueue 關心的是 apple 相關的話題;而 bananaQueue 關心的是 banana 相關的話題。 - 所以可以推斷出,消息在發送時,可以指定話題相關的信息,以便消息能被關注該話題的隊列接收。
經過上面的分析,我們就知道了消息發送時通過攜帶話題信息,交換機會將該消息路由到關心該話題的隊列中。
3.6 創建消費者
接下來,我們就可以定義消息的消費者李四、趙五了。他倆分別關心蘋果采購消息和香蕉采購消息。也就是監聽蘋果消息隊列和香蕉消息隊列。
實例:
/**
* 消息隊列接收
*/
@Component
public class RabbitReceiver {
/**
* lisi負責監聽apple-queue
*/
@RabbitListener(queues = "apple-queue")
public void lisi(String msg) {
System.out.println("李四知道:" + msg);
}
/**
* zhaowu負責監聽banana-queue
*/
@RabbitListener(queues = "banana-queue")
public void zhaowu(String msg) {
System.out.println("趙五知道:" + msg);
}
}
3.7 測試
運行啟動類,從 RabbitMQ 管理界面可以看到已生成指定名稱的隊列了。
此時我們定義一個控制器用于發起測試,直接使用 rabbitTemplate 發送消息即可。
實例:
@RestController
public class TestController {
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/test")
public void test() {
// 發送消息 參數分別為:交換機名稱、路由鍵、消息內容
rabbitTemplate.convertAndSend("exchange-topic", "apple", "蘋果來了10斤");
rabbitTemplate.convertAndSend("exchange-topic", "banana", "香蕉來了5斤");
rabbitTemplate.convertAndSend("exchange-topic", "apple.banana", "蘋果來了8斤;香蕉來了20斤");
}
}
convertAndSend() 方法的第 1 個參數表示交換機,第 2 個參數表示路由鍵(消息的話題),第 3 個是消息內容。
所以第 1 個消息會被 apple-queue 接收,第 2 個消息會被 banana-queue 接收,第 3 個消息會被兩個隊列接收。
我們啟動項目,然后訪問 http://127.0.0.1:8080/test
,控制臺輸出如下,驗證成功。
趙五知道:香蕉來了5斤
李四知道:蘋果來了10斤
趙五知道:蘋果來了8斤;香蕉來了20斤
李四知道:蘋果來了8斤;香蕉來了20斤
4. 小結
本小節通過一個實際應用場景,演示了 Spring Boot 中使用 RabbitMQ 消息隊列的方法。
至此, Spring Boot 的內容就全部結束了。紙上得來終覺淺,絕知此事要躬行。任何的實用技能都需要在不斷練習與使用中感悟、完善、提升, Spring Boot 也不例外。
所以還沒有使用 Spring Boot 的朋友,抓緊上手吧!