什麼是rabbitmq
RabbitMQ是用Erlang語言開發的開源消息隊列系統,基於AMQP協議來實現(AMQP的主要特徵是面向消息、隊列、路由、可靠性、安全)。支持多種客戶端,如:Python、Ruby、.NET、Java等,支持AJAX。用於在分佈式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現很出色。本文着重介紹springboot和rabbitmq的集成,故在此不與其他mq進行比較
RabbitMQ比較重要的幾個概念:
虛擬主機:RabbitMQ支持權限控制,但是最小控制粒度爲虛擬主機。一個虛擬主機可以包含多個交換機、隊列、綁定。
交換機:RabbitMQ分發器,根據不同的策略將消息分發到相關的隊列。
隊列:緩存消息的容器。
綁定:設置交換機與隊列的關係。
P爲發送消息(生產者)、X爲交換機、Q爲消息隊列、C爲接收消息(消費者)
爲什麼要用rabbitmq
-
同步變異步
大家可以設想一個實際場景,我們有一個接口叫sendBackend,需要給系統所有裏的用戶發送短信(調用sendMessage)和推送消息(pushMessage),假設系統裏有10萬用戶甚至更多,如果同步去調用的話後果將不堪設想,這個時候rabbitmq就可以閃亮登場了,我們只需要在sendBackend的時候將用戶信息放入到rabbitmq中即可 -
流量削峯
通過消息隊列設置請求最大值,超過閥值的拋棄或者轉到自定義頁面 -
rabbitmq採用信道通信。不採用tcp直接通信
a.tcp的創建和銷燬開銷大,創建3次握手,銷燬4四次分手
b.高峯時成千上萬條的鏈接會造成資源的巨大浪費,而且操作系統沒秒處理tcp的數量也是有數量限制的,必定造成性能瓶頸
c.一條線程一條信道,多條線程多條信道,公用一個tcp連接。一條tcp連接可以容納無限條信道(硬盤容量足夠的話),不會造成性能瓶頸 -
低內聚高耦合
安裝(本文環境爲win10)
- 安裝Erlang,我們知道rabbitmq是基於Erlang語言開發的,所以安裝rabbitmq之前我們需要先安裝erlang,下載地址:http://www.erlang.org/downloads
安裝完之後在環境變量中配置erlang,配置完之後在cmd中輸入erl,看到輸出信息便配置成功了 - 安裝rabbitmq 下載地址(http://www.rabbitmq.com/download.html)
裝rabbitmq的插件,進入到rabbitmq目錄下sbin目錄,
執行rabbitmq-plugins enable rabbitmq_management命令進行安裝,最後雙擊rabbitmq-server.bat啓動,啓動成功之後訪問http://localhost:15672即可。
實戰(本文將以rabbitmq的默認交換機和top交換機爲例)
項目目錄如下
rabbitmq-producer爲生產者,rabbitmq-consumer爲消費者,rabbitmq-common爲公共模塊
1. 基礎模塊配置(生產者和消費者的配置信息一致)
a. 集成rabbitmq
<dependencies>
<dependency>
<groupId>com.rockcode</groupId>
<artifactId>rabbitmq-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
b.添加rabbitmq服務配置(配置文件)
#rabbitmq相關
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
2.交換機----------DirectExchange
DirectExchange是RabbitMQ的默認交換機,直接使用routingKey匹配隊列
2.1)添加一個配置類(消費者)
配置一個routingKey爲band.punk的消息隊列
@Configuration
public class DirectConfig {
//配置一個routingKey爲band.punk的消息隊列
@Bean
public Queue punkLiveNotify(){
return new Queue("band.punk");
}
}
2.2)添加一個消息監聽類(消費者)
監聽routingKey爲band.punk的隊列消息
@Component
public class PunkLiveService {
@RabbitHandler
@RabbitListener(queues = "band.punk")
public void revieve(String name){
System.out.println("band.punk recieve"+name);
}
}
2.3)添加一個消息發送類(生產者)
將消息發送至默認的交換機且routingKey爲band.punk
@Component
public class PunkLiveSender {
@Autowired
private AmqpTemplate amqpTemplate;
public void sender(String name){
amqpTemplate.convertAndSend("band.punk",name);
}
}
2.4)添加一個測試入口(生產者)大家也可以使用junit來進行測試
@RestController
public class PunkLiveController {
@Autowired
private PunkLiveSender punkLiveSender;
@RequestMapping("sendPunkBand")
public void sendPunkBand(){
punkLiveSender.sender("smzb");
}
}
訪問sendPunkBand接口之後我們會在消費端看到輸入smzb,證明消息的發送接收已經完成
3.交換機----------TopicExchange
TopicExchange是按規則轉發消息,是交換機中最靈活的一個。也是最常用的一個。
3.1)添加一個配置類(消費者)
配置一個routingKey爲band.china.的消息隊列並綁定在bandExchange交換機上(交換機的匹配規則爲band.china.)
@Configuration
public class TopicConfig {
@Bean
public Queue bandQueue() {
return new Queue("band.china");
}
@Bean
public TopicExchange bandExchange() {
return new TopicExchange("bandExchange");
}
@Bean
public Binding bindingBandExchange(Queue bandQueue,TopicExchange topicExchange){
return BindingBuilder.bind(bandQueue).to(topicExchange).with("band.china.*");
}
}
3.2)添加一個消息監聽類(消費者)
監聽routingKey爲band.china.*的隊列消息
@Component
public class BandService {
@RabbitHandler
@RabbitListener(queues = "band.china")
public void recieveObject(BandInfo bandInfo) {
System.out.println(bandInfo.toString());
}
}
3.3)添加一個消息發送類(生產者)
sendSxBand 發送消息至bandExchange交換機而且routingKey爲band.china.*
@Component
public class BandSender {
@Autowired
private AmqpTemplate amqpTemplate;
/**
* sendSxBand 發送消息至bandExchange交換機而且routingKey爲band.china.*
*/
public void sendSxBandInfo(){
BandInfo bandInfo=new BandInfo();
bandInfo.setBandCity("陝西");
bandInfo.setBandName("許巍");
amqpTemplate.convertAndSend("bandExchange","band.china.shanxi",bandInfo);
}
}
3.3)添加一個測試類
@RestController
public class BandController {
@Autowired
private BandSender bandSender;
@RequestMapping("sendSxBandInfo")
public void sendSxBandInfo(){
bandSender.sendSxBandInfo();
}
}
訪問sendSxBandInfo接口,我們可以看到在消費者日誌臺打印出具體的信息,證明消息的發送接收過程已經完成
知識點:
TopicExchange交換機支持使用通配符*、#
*號只能向後多匹配一層路徑。
#號可以向後匹配多層路徑。
源碼下載:https://gitee.com/pkfd/springboot-rabbitmq
如有需要可以關注公衆號互動溝通