注:這是RabbitMQ-java版Client的指導教程翻譯系列文章,歡迎大家批評指正
第一篇Hello Word了解RabbitMQ的基本用法
第二篇Work Queues介紹隊列的使用
第三篇Publish/Subscribe介紹轉換器以及其中fanout類型
第四篇Routing介紹direct類型轉換器
第五篇Topics介紹topic類型轉換器
第六篇RPC介紹遠程調用
預備條件
這篇指導教程的前提是已經下載了RabbitMQ并且運行在本機上默認端口號5672。如果你使用不同的主機,端口號或者相關認證,連接設置需要做一些調整。
尋求幫助
如果你在閱讀這個系列指導教程時有任何的問題,可以通過郵件聯系我們。
介紹(Introduction)
RabbitMQ是一個消息中間件:它接受并轉發消息。你可以把它看成是一個郵局:當你把想投遞的郵件放在郵箱中時,知道郵遞員終會把郵件派送給收件人。這個比喻中,RabbitMQ是郵箱,郵局和郵遞員。
RabbitMQ和郵局之間最大的不同是前者不需要處理紙張,就可以接受,存儲并且傳發二進制數據的消息。
通常,RabbitMQ和消息傳送會有一些專業術語。
生產和發送的意義是一樣的,一個應用發送消息就是生產者:
隊列類似郵局中的郵箱存在于RabbitMQ中,盡管消息是在RabbitMQ和應用間傳送,但消息只存儲在隊列中。隊列的大小只受限于主機的內存或者硬盤的大小,本質上是有無限大的緩存區間。許多生產者可以發送消息到一個隊列中,當然需要消費者也可以從一個隊列中接受消息。我們用下列圖形代表隊列:
消費和接受有著同樣的意思,一個應用常在等待接受消息就是消費者:
注解:生產者,消費者以及消息中間件并不會存在于同一個主機上,且大部分應用確實也不會這樣做。
"Hello World"
(using the java Client ,我是搞Android開發的,所以語言沒得選:java是當今世界上最流行的語言)
在這篇指導教程中,我們將用Java寫兩個應用,發送一條簡單消息的生產者,和接受消息并且將消息打印出來的消費者。我們將會省略掉部分Java API的具體細節,專注于開始學習最簡單的"Hello World"消息傳遞。
在下面的圖表中,"P"表示生產者和"C"表示消費者,中間的盒子表示隊列-消費者的消息緩存在RabbitMQ中。
MabbitMQ的java版本客戶端的依賴包(The Java Client library)
RabbitMQ支持多種協議,這篇指導教程中使用AMQP協議,這是一個開源,多用途的消息傳遞協議。針對不同的語言,RabbitMQ提供專門的客戶端版本,目前我們使用的是Java版本。
下載Java Client library并且依賴于SLF4J API和SLF4J Simple,拷貝這些文件到你的工作目錄下,跟其它的java文件一塊放。
請注意SLF4J Simple只是在指導教程中使用,而在真正的生產項目中,應該使用更強大的日志包,像Logback。
現在我們有了Java版本的客戶端RabbitMQ和依賴包,可以寫些代碼了。
發送(Sending)
我們將稱消息發布者(發送者)為Send,消息消費者(接受者)為Recv。發布者將會連接上服務端RabbitMQ,發送一條簡單的消息,然后退出。
在Send.java中,我們需要引入一些類:
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
創建類并且給隊列命名:
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws java.io.IOException {
...
}
}
接著我們連接服務端:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost"); //factory可以設置主機Ip,端口號,認證信息等連接服務端
Connection connection = factory.newConnection(); //創建連接
Channel channel = connection.createChannel(); //創建通道
這是抽象的Socket(套接宇)連接方式,注意協議版本的差異和驗證等等都取決于我們自己。我們連接到本機的RabbitMQ上,所以才是localhost。如果我們想連接到不同的機器上的RabbitMQ上,可以簡單說明該機器的名稱和IP地址。(下面代碼是我擅自添加的)
factory.setPort(8080);
factory.setUsername("admin");
factory.setPassword("password"):
下一步創建通道(channel),大部分的事情都是在這里處理。
我們必須先聲明發送消息去的隊列,然后發送消息到隊列中:
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();
這里是Send.java的源碼(這么簡答的代碼,不想貼)
發送失敗
如果這是你第一次使用RabbitMQ,并且你沒有看到發送的消息,可能傷腦筋了:哪里出了問題?可能是消息中間件開始的時候可用硬盤空間不足(默認的至少剩余200MB),因此會拒絕接收消息。查看消息中間件的日志文件和如果有必要的話減少這些限制。這篇配置文檔將會告訴你如何去設置硬盤剩余空間的限制。
接受(Receiving)
發布者相對應的就是我們的接受者,接受者是接受從RabbitMQ推送過來的消息,而不像發布者是發布消息到RabbitMQ中。我們設置了對消息的監聽,并且打印出消息:
Recv.java的引入類和Send.java有三個是一樣的:
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
這個額外的DefaultConsumer是一個實現了Consumer接口的類,我們用來緩存由服務端推送給接受者的消息。
和發布者開始的創建是類似的,打開連接(connection)和通道(channel),并且聲明一條可以消費消息的隊列。注意這個隊列是匹配send發布消息的隊列:
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws java.io.IOException, java.lang.InterruptedException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
...
}
}
請注意消費者也聲明了隊列,因為我們可以在創建發布者之前先創建消費者。我們像確保這些隊列已經存在了,然后就可以從隊列中消費消息。
將要告訴 服務端要從隊列中分發消費者的消息,然后就會異步的推送消息給消費者。我們提供了一個callBack的表單對象用于緩存消息直到消費者已經獲取到它們。這個就是DefaultConsumer子類的工作:
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(" [x] Received '" + message + "'");
}
};
channel.basicConsume(QUEUE_NAME, true, consumer);
綜合
你可以在RabbitMQ java客戶端編譯這些類:
javac -cp amqp-client-4.0.2.jar Send.java Recv.java
在一個終端上運行消費者,你需要rabbitmq-client.jar和一些依賴:
java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Recv
接著運行生產者:
java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Send
在Windows系統上,使用分好代替冒號去分割每一個條目。
通過RabbitMQ,消費者將會打印出從生產者接受的消息,并且一直運行等待著接受消息(可以使用Ctrl +C去停止運行),因此可以嘗試從另外一個終端來運行生產者。
第一節的內容大致翻譯完了,這里是原文的鏈接。接著進入下一節:Work Queues。
終篇是我對RabbitMQ使用理解的總結文章,歡迎討教。
--謝謝--