你是否聽說過或者使用過隊列?
你是否聽說過或者使用過消息隊列?
你是否聽說過或者使用過RabbitMQ?
提到這幾個詞,用過的人,也許覺得很簡單,沒用過的人,也許覺得很復雜,至少在我沒使用消息隊列之前,聽別人提到消息隊列,都感覺很復雜,很高深。
好了,言歸正傳,本篇博客我們就講解下什么是消息隊列,RabbitMQ環境的安裝配置,最后通過一個Hello World示例了解下RabbitMQ的使用方法。
1. 基本概念講解
1.1 隊列(Queue)
隊列是常用的數據結構之一,是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的后端(rear)進行插入操作。
進行插入操作的端稱為隊尾,進行刪除操作的端稱為對頭。
在Java中,java.util包下已經有隊列的相關實現,我們可以直接使用。
1.2 消息隊列(Message Queue)
消息是計算機/應用間傳送的數據單位,可以非常簡單,例如只包含文本字符串,也可以很復雜,可能包含嵌入對象。
消息隊列是在消息的傳輸過程中保存消息的容器。
消息傳輸時,先發送到隊列,隊列的主要目的是提供路由並保證消息的傳遞,如果發送消息時接收者不可用,消息隊列會保留消息,直到可以成功的傳遞它。
可以把消息隊列理解成快遞公司,你需要寄一個物件(消息)給你的朋友,快遞公司收到物件會保證物件送到你的朋友手中,可能存在多次寄送才送達成功的情況,比如第一次送過去,你朋友不在家。
也許有人好奇,為什么我們不直接使用JDK自帶的隊列,而是要使用消息隊列呢?
這是因為JDK自帶的隊列都存儲在內存中,一但應用或者服務器掛了,消息就丟失了,使用消息隊列可以避免消息丟失問題(注意不是100%不丟失),就像快遞公司會保證你的物件寄到你的朋友手中,但肯定有丟件的幾率。
1.3 RabbitMQ
RabbitMQ是用Erlang語言開發的基於高級消息隊列協議(AMQP)的消息隊列中間件。
因為它開源,而且版本更新快,所以在國內互聯網公司被廣泛使用。
其它使用的消息中間件還有ActiveMQ,RocketMQ,Kafka等,有興趣的同學可以自行研究。
還有2個專業術語要了解下:
生產者:發送消息的應用程序被稱為生產者。
消費者:接收消息的應用程序被稱為消費者。
2. RabbitMQ安裝及配置
了解完基本概念,讓我們在本機上安裝下RabbitMQ,因為它是基於Erlang語言開發的,所以我們要先安裝Erlang。
2.1 Erlang安裝及配置
Erlang下載地址:http://www.erlang.org/downloads
因為我的電腦是Windows 64位系統,所以我下載的是64位的,系統是32位的同學注意下版本。
安裝過程比較簡單,以下為部分截圖:
安裝完成后,需要新建個環境變量(打開方式:計算機--右鍵--屬性--高級系統設置--高級--環境變量):
ERLANG_HOME E:\Program Files\erl10.4(修改為你的安裝路徑)
2.2 RabbitMQ安裝及配置
RabbitMQ下載地址:https://www.rabbitmq.com/install-windows.html
安裝過程也比較簡單,以下為部分截圖:
安裝完成后,在cmd窗口中執行以下命令激活RabbitMQ Manage Plugin
"E:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.15\sbin\rabbitmq-plugins.bat" enable rabbitmq_management
然后執行命令重啟RabbitMQ服務:
net stop RabbitMQ && net start RabbitMQ
如果你的cmd窗口不是以管理員身份打開的,會出現如下報錯信息
解決方法也很簡單,以管理員身份打開cmd窗口執行命令即可
關於這一步,可以不使用命令重啟RabbitMQ服務,而是打開Windows的服務列表,找到RabbitMQ服務,重啟即可。
到這一步,RabbitMQ的安裝就算完成了,其中有幾個默認值,我們要知曉下:
- 默認的端口號:5672
- 默認的用戶是guest guest
- 管理后台的默認端口號:15672
瀏覽器輸入http://localhost:15672/,我們可以看到RabbitMQ的管理后台,然后使用默認的guest賬號登錄,在這個后台,可以完成新建用戶,配置用戶角色,新建隊列等操作,當然,如果有的同學比較喜歡命令行操作,也都有相對應的命令來完成操作,關於這些內容,后續單獨再寫博客講解。
3. Hello World示例
既然RabbitMQ環境安裝好了,那么我們通過1個簡單的示例來看下效果。
首先在pom文件中,添加依賴:
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.0</version>
</dependency>
然后新建一個生產者類(Producer),用來新建一個隊列'hello',然后往隊列里發送消息‘Hello World’:
package com.zwwhnly.springbootaction.rabbitmq.helloworld;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
// 創建連接
ConnectionFactory factory = new ConnectionFactory();
// 設置 RabbitMQ 的主機名
factory.setHost("localhost");
// 創建一個連接
Connection connection = factory.newConnection();
// 創建一個通道
Channel channel = connection.createChannel();
// 指定一個隊列,不存在的話自動創建
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 發送消息
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
// 關閉頻道和連接
channel.close();
connection.close();
}
}
運行代碼,在RabbitMQ管理后台,會看到隊列新建成功,並且有1個消息待消費:
最后我們新建一個消費者類(Consumer),用來消費這個消息:
package com.zwwhnly.springbootaction.rabbitmq.helloworld;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
private final static String QUEUE_NAME = "hello";
public static void main(String[] args) throws IOException, TimeoutException {
// 創建連接
ConnectionFactory factory = new ConnectionFactory();
// 設置 RabbitMQ 的主機名
factory.setHost("localhost");
// 創建一個連接
Connection connection = factory.newConnection();
// 創建一個通道
Channel channel = connection.createChannel();
// 指定一個隊列
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// 創建隊列消費者
com.rabbitmq.client.Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("Received Message '" + message + "'");
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
}
}
運行代碼,我們會發現控制台輸出:
Received Message 'Hello World!'
此時再看下RabbitMQ管理后台,會發現隊列'hello'待消費的消息為0:
是不是覺得挺簡單的呢,趕緊在本機安裝試試吧!
4. 源碼及參考
源碼地址:https://github.com/zwwhnly/springboot-action.git,歡迎下載。
【譯】RabbitMQ 實戰教程(一) Hello World!
原創不易,如果覺得文章能學到東西的話,歡迎點個贊、評個論、關個注,這是我堅持寫作的最大動力。
如果有興趣,歡迎添加我的微信:zwwhnly,等你來聊技術、職場、工作等話題(PS:我是一名奮斗在上海的程序員)。