**前面聲明本文都是RabbitMQ的官方指南翻譯過來的,因爲本人水平有限不免有翻譯不當的地方,如發現不對的地方,請聯繫下我,好及時改正。**好了,正文開始:html
RabbitMQ 是一個消息代理。這主要的原理十分簡單,就是經過接受和轉發消息。你能夠把它想象成郵局:當你將一個包裹送到郵局,你會相信郵遞員先生最終會將郵件送到接件人手上。RabbitMQ就比如一個郵箱,郵局或郵遞員。java
郵局和RabbitMQ兩種主要的不一樣之處在於,RabbitMQ不處理文件,而是接受,並存儲和以二進制形式將消息轉發。git
RabbitMQ,在消息的傳送過程當中,咱們使用一些標準稱呼。github
生產過程就像發送過程,發送消息的程序就是一個生產者,咱們使用「P」來描述它。shell
隊列是比如郵筒的稱呼,它位於RabbitMQ內部,雖然消息流經過RabbitMQ和你的應用程序,可是它們僅僅存儲在隊列中。一個隊列沒有範圍限制,你能夠想存儲多少就存儲多少,本質上來講它是無限大的緩存。多個生產者能夠經過一個隊列發送消息,一樣多個消費者也能夠通同一個消息隊列中接收消息。隊列是畫成這樣,名字在它的上面:windows
消費過程與接收類似,一個消費者一般是一個等着接受消息的程序,咱們使用"C"來描述:數組
注意,那生產者,消費者和代理者不須要必定在一個機器上,事實上,大多數應用程序中,他們並不在一個機器上。緩存
###"Hello World" ###(使用java客戶端)服務器
在這部分指南中,咱們將要使用java寫兩個程序;一個發送簡單消息的生產者和一個接收消息並輸出出來的消費者。咱們會忽視掉一些Java API的細節,爲了開始僅僅精選在這簡單的事情上,這是一個"Hello World"消息。異步
Java 客戶端庫 RabbitMQ 遵循AMQP協議,那是一個開放的,而且通用的消息協議。在不一樣語言中有數種AMQP客戶端,咱們使用由RabbitMQ提供的Java客戶端。 下載客戶端庫包,檢驗簽名,將它解壓縮到你的工做路徑,從解壓到的路徑中提取JAR文件:
$ unzip rabbitmq-java-client-bin-*.zip $ cp rabbitmq-java-client-bin-*/*.jar ./
(RabbitMQ Java客戶端也存在Maven中央庫中,
groupId
是com.rabbitmq
,artifactId
是amqp-client
.)
如今咱們已經有了Java客戶端和依賴文件,咱們能夠寫一些代碼了。
###發送
咱們將會讓咱們的消息發送者發送消息,咱們的接收者接收消息。發送者鏈接到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"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel();
抽象的socket鏈接,注意協議版本的處理以及受權,諸如此類的事情。 這裏咱們鏈接到本地機器上的代理,所以它是localhost
。若是咱們想鏈接到不一樣機器上的代理,只須要說明它的主機名和IP地址。
接下來咱們建立一個通道,獲取操做的大多數API都位於這上。
對於發送,咱們必須聲明一個發送隊列,而後咱們把消息發送到這個隊列上:
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 + "'");
Declaring a queue is idempotent - it will only be created if it doesn't exist already. The message content is a byte array, so you can encode whatever you like there.
Lastly, we close the channel and the connection; 聲明一個隊列是冪等的,僅僅在要聲明的隊列不存在時才建立。消息內容是二進制數組,因此你能夠隨你喜愛編碼。
channel.close(); connection.close();
Here's the whole Send.java class.
發送沒有起做用
若是你是第一次使用RabbitMQ而且你沒有看到"Sent"消息,你可能抓耳撓腮的想究竟是哪裏出的問題。多是代理啓動時沒有足夠空間(默認它須要至少1Gb 空間),所以拒絕接受消息。經過檢查代理的日誌文件來肯定這個問題,必要狀況下能夠下降限制大小。配置文件的文檔將會告訴你怎樣設置
disk_free_limit
。
###接收
上面代碼是構建咱們的發送者。咱們的接收者是從RabbitMQ中提取消息,因此不像發送者那樣發送一個簡單的消息,咱們須要一直運行監聽消息而且輸出消息。
在Recv.java中的代碼有與Send中幾乎相同的引用:
import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.Connection; import com.rabbitmq.client.Channel; import com.rabbitmq.client.QueueingConsumer;
這額外的QueueingConsumer
類是用來緩存從服務器那裏發出來的信息。
跟建立發送者相同,咱們打開一個鏈接和一個通道,聲明一個咱們要消費的隊列。注意要與發送的隊列相匹配。
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"); ... } }
注意咱們在這裏一樣聲明瞭一個隊列。覺得咱們可能在發送者以前啓動接收者,在咱們從中獲取消息以前咱們想要肯定這隊列是否真實存在。 咱們通知服務器經過此隊列給咱們發送消息。所以服務器會異步的給咱們推送消息,在這裏咱們提供一個回調對象用來緩存消息,直到咱們準備好再使用它們。這就是QueueingConsumer
所作的事。
QueueingConsumer consumer = new QueueingConsumer(channel); channel.basicConsume(QUEUE_NAME, true, consumer); while (true) { QueueingConsumer.Delivery delivery = consumer.nextDelivery(); String message = new String(delivery.getBody()); System.out.println(" [x] Received '" + message + "'"); }
QueueingConsumer.nextDelivery()
在另外一個來自服務器的消息到來以前它會一直阻塞着。
這是整個Recv.java類。 ###把全部放在一塊兒
你能夠在RabbitMQ Java客戶端的類路徑上編譯這些文件:
$ javac -cp rabbitmq-client.jar Send.java Recv.java
爲了運行它們,你須要rabbitma-client.jar
和它在類路徑上的的依賴文件。在一個終端上,運行發送者:
$ java -cp .:commons-io-1.2.jar:commons-cli-1.1.jar:rabbitmq-client.jar Send
而後,運行接收者:
$ java -cp .:commons-io-1.2.jar:commons-cli-1.1.jar:rabbitmq-client.jar Recv
在windows環境中,咱們使用分號代替冒號來分隔類路徑上的選項。
接收者將會輸出從RabbitMQ中獲取到來自發送者的消息。接收者會一直保持運行,等待消息(使用Ctrl-C
中止),因此試着用另外一個終端運行發送者。 若是你想檢驗隊列,試着使用rabbitmqctl list_queues0
。
Hello World!
時間移動到第二部分,構建一個簡單的工做隊列。
提示 爲了保存輸入,你能夠將類路徑設置到環境變量中
\$ export CP=.:commons-io-1.2.jar:commons-cli-1.1.jar:rabbitmq-client.jar \$ java -cp $CP Send
或者在 Windows環境中:
\> set CP=.;commons-io-1.2.jar;commons-cli-1.1.jar;rabbitmq-client.jar \> java -cp %CP% Send