一:RabbitMQ簡介
RabbitMQ是使用Erlang開發實現支持了AMQP協議,並且支持多客戶端類型的比較流行的消息隊列中間件,相對的還有很多開源MQ產品如RocketMQ、ActiveMQ、Kafka等等
MQ總結而言最大的三個特點就是異步、削峯、解耦,如下圖所示。其餘複雜的概念就不照本宣科抄襲了,反正寫在這裏也是廢話。最簡單的概括就是存儲數據的容器,與MySQL數據庫、Redis數據庫等類似,區別在於自身實現特點決定了應用場景
二:基本結構設計
上面一節介紹了MQ隊列的作用,接下來就是給RabbitMQ寬衣解帶看看裏面是啥貨色。如下圖總覽所示一個完整的RabbitMQ模型圖
2.1 生產者
負責生產數據並送到消息隊列供消費者使用,生產過程中可能會給消息數據配置屬性標籤等,方便後續邏輯處理
2.2 交換器
生產者與儲存數據的隊列並不直接聯繫,中間依靠交換器進行通信。消息發送到交換器後交換器根據消息的routing key屬性與binding屬性比較轉發給隊列
2.3 隊列
真正存儲消息的位置,與交換器依靠binding進行綁定。一個隊列可以綁定多個交換器,換而言之,一個交換器也可以對應多個隊列。兩者之間屬於多對多關係
2.4 消費者
只關心隊列不關心交換器,直接從隊列中獲取數據進行消費即可
2.5 兩個綁定
routing key其實可以算是消息的屬性,在生產者發送消息時攜帶。binding key是申明交換器與隊列的綁定關係,需要提前申請。當消息攜帶routing key進來以後,交換器會比較兩者,然後將消息轉發到符合規則binding對應的隊列中
三:創建連接
RabbitMQ屬於一個應用,就好像數據庫服務一樣。使用服務應用時需要在程序中與應用創建連接,RabbitMQ中考慮到連接創建、銷燬帶來的性能損耗,使用信道的概念。比較抽象的一個內容,具體關係如下圖所示
所以具體關係就是:連接工廠 --> 連接 --> 信道(通道),當然圖中沒有體現連接工廠的概念,但是這並不耽誤我們去理解這個內容。如果想要模仿下列代碼請先引入相關依賴,本文都將在SpringBoot項目上做操作演示,如果沒有服務應用可以移步RabbitMQ部署
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
// 連接工廠獲取Connection
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("RabbitMQ應用部署IP");
connectionFactory.setPort(RabbitMQ應用暴露端口);
connectionFactory.setUsername("RabbitMQ應用賬號");
connectionFactory.setPassword("RabbitMQ應用密碼");
Connection connection = connectionFactory.newConnection();
// 由連接創建信道通道
Channel channel = connection.createChannel();
// 等待查看控制檯效果
InputStream in = System.in;
in.read();
四:創建RabbitMQ結構
// 創建交換器
String exchangeName = "directExchange";
hannel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT,true);
// 創建隊列
String queueName = "testQueue";
channel.queueDeclare(queueName,true,false,false,null);
// 綁定交換器與隊列
String binding = "testBinding";
channel.queueBind(queueName,exchangeName,binding);
五:發送消息
// 發送消息
String routingKey = "testBinding";
String message = "測試消息";
channel.basicPublish(
exchangeName,routingKey,
MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes()
);
六:消費消息
// 消費消息
String queueName = "testQueue";
channel.basicConsume(queueName,true,"testConsumerTag",new DefaultConsumer(channel){
@Override
public void handleDelivery (String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
}
});