文章主要翻譯自RabbitMQ官方文檔,主要是為了練習英語翻譯,順便學習一下RabbitMQ😶
其中也記錄了一些爬過的坑
Introduction
RabbitMQ is a message broker. The principal idea is pretty simple: it accepts and forwards messages. You can think about it as a post office: when you send mail to the post box you're pretty sure that Mr. Postman will eventually deliver the mail to your recipient. Using this metaphor RabbitMQ is a post box, a post office and a postman.
The major difference between RabbitMQ and the post office is the fact that it doesn't deal with paper, instead it accepts, stores and forwards binary blobs of data ?messages.
RabbitMQ, and messaging in general, uses some jargon.
譯:RabbitMQ是一個消息中間件(message broker)。它的核心思想(principal idea)非常簡單:它可以接受和發送消息。你可以把它就想象成一個寄信過程:當你寄信時,你要把信投到郵箱里,然后你相信一定會有郵遞員把信取走,并且安全無誤的把信送到收件人的手中。一個恰當的比喻,RabbitMQ扮演了三個角色,它是一個郵箱,也是一個郵局,還是一個郵遞員。
當然,它和郵局最重要的區別是,RabbitMQ存儲、發送的不是紙(廢話),而是二進制的數據。
RabbitMQ在使用中有一些術語。
Producing?means nothing more than sending. A program that sends messages is a?producer. We'll draw it like that, with "P":
譯:“生產者”其實和“消息發送”意思差不多。代表一個發送消息的生產者。我們簡稱它為“P”:
Aqueue is the name for a mailbox.It lives inside RabbitMQ.Although message flow through RabbitMQ and your applications,they can be stored
only inside a queue.A queue is not bound by any limits,it can store as many messages as you like - it's essentially an infinite buffer. Many producers
can send messages that go to one queue, many consumers can try to receive data from one queue. A queue will be drawn as like that, with its name
above it:
譯:一個隊列可以比喻作是一個郵箱。它存在于RabbitMQ中。雖然消息的傳輸需要通過RabbitMQ和你的應用程序,這些消息只能保存在隊列中。
一個隊列是沒有什么約束和限制的,只要你愿意它可以存儲很多消息,本質上來說它就是一個無窮的緩沖區。許多消息生產者可以向一個
隊列發送消息,同樣許多消費者可以嘗試接收一個隊列中的消息。下圖所示就是一個隊列:
Consuming?has a similar meaning to receiving. A?consumer?is a program that mostly waits to receive messages. On our drawings it's shown with "C":
譯:消費也可以理解為接收。一個接收者就是一個等待接收消息的程序。下圖就是一個接受者“C”:
Note that the producer, consumer, and broker do not have to reside on the same machine; indeed in most applications they don't.
譯:注意,生產者、消費者、中間件不必在同一臺機器上。事實上他們沒有在一臺機器上。
"Hello World"
(using the Java Client)
In this part of the tutorial we'll write two programs in Java; a producer that sends a single message, and a consumer that receives messages and prints them out. We'll gloss over some of the detail in the Java API, concentrating on this very simple thing just to get started. It's a "Hello World" of messaging.
In the diagram below, "P" is our producer and "C" is our consumer. The box in the middle is a queue - a message buffer that RabbitMQ keeps on behalf of the consumer.
譯:這部分的內容會指導我們用Java語言寫幾個程序;一個用來發送單獨消息的生產者,和一個接收消息的消費者,并將他們輸出出來。我們會忽略一些調用JavaAPI的細節,只關心這個簡單的例子可以跑起來。
在下方的圖表中“P”代表我們的生產者,“C”代表我們的消費者。它們中間這個盒子是隊列——它保持著RabbitMQ代表消費者的消息緩沖區。
The Java client library
RabbitMQ speaks multiple protocols. This tutorial uses AMQP 0-9-1, which is an open, general-purpose protocol for messaging. There are a number of clients for RabbitMQ in?many different languages. We'll use the Java client provided by RabbitMQ.
Download the?client library package, and check its signature as described. Unzip it into your working directory and grab the JAR files from the unzipped directory:
$ unzip rabbitmq-java-client-bin-*.zip
$ cp rabbitmq-java-client-bin-*/*.jar ./
(The RabbitMQ Java client is also in the central Maven repository, with the groupIdcom.rabbitmq?and the artifactId?amqp-client.)
譯:首先需要引入Java client庫的依賴,可以通過下載jar包,或者使用Maven構建工具,下面補充一下官方文檔沒有舉例的maven配置:
com.rabbitmq
amqp-client
3.3.4
Now we have the Java client and its dependencies, we can write some code.
譯:現在我們有了RabbitMQ封裝好的client和這個依賴,下面我們就可以敲一些代碼了。
Sending
We'll call our message sender Send and our message receiver Recv. The sender will connect to RabbitMQ, send a single message, then exit.
譯:我們調用我們的消息發送者“Send”和我們的消息接受者“Recv”。這個發送者會連接RabbitMQ,發送一條消息,然后退出。
In?Send.java, we need some classes imported:
譯:在Send.java中,我們需要引入一些類:
1 importcom.rabbitmq.client.ConnectionFactory;2 importcom.rabbitmq.client.Connection;3 import com.rabbitmq.client.Channel;
Set up the class and name the queue:
譯:建立類并聲明隊列的名字:
1 public classSend {2 private final static String QUEUE_NAME = "hello";3
4 public static voidmain(String[] argv)5 throwsjava.io.IOException {6 ...7 }8 }
then we can create a connection to the server:
譯:然后我們就可以和server來建立一個連接:
1 ConnectionFactory factory = newConnectionFactory();2 factory.setHost("localhost");3 Connection connection =factory.newConnection();4 Channel channel = connection.createChannel();
注意,這里也可以設置Connection的端口號,通過:
factory.setPort(5672);
查看源碼,默認的端口是:
public static final int DEFAULT_AMQP_OVER_SSL_PORT = 5671;
The connection abstracts the socket connection, and takes care of protocol version negotiation and authentication and so on for us. Here we connect to a broker on the local machine - hence thelocalhost. If we wanted to connect to a broker on a different machine we'd simply specify its name or IP address here.
Next we create a channel, which is where most of the API for getting things done resides.
To send, we must declare a queue for us to send to; then we can publish a message to the queue:
譯:這個連接抽象自socket連接,并且我們負責協議的版本協商和認證等方面。在這里我們連接一個本機的中間件——也就是“localhost”。如果我們想連接到其它機器上的中間件,我們需要簡單的制定它的機器名或者IP地址。接下來我們創建一個通道,要做的大多事情都在這個API中。發送,我們必須聲明一個消息隊列用來為我們發送消息;然后我們就可以發送消息給隊列了。
1 channel.queueDeclare(QUEUE_NAME, false, false, false, null);2 String message = "Hello World!";3 channel.basicPublish("", QUEUE_NAME, null, message.getBytes());4 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;
譯:我們聲明的這個隊列是冪等的——如果不存在隊列,則創建一個。消息的內容是一個字節數組,所以你可以隨心所欲的編碼你要發送的內容。
Lastly, we close the channel and the connection;
譯:最后,我們關閉建立的通道和連接。
1 channel.close();2 connection.close();
下面是Send.java完整源碼,其中注釋有聲明隊列和發送消息時參數列表說明:
1 packageProducer;2
3 importcom.rabbitmq.client.Channel;4 importcom.rabbitmq.client.Connection;5 importcom.rabbitmq.client.ConnectionFactory;6
7 importjava.io.IOException;8
9 /**
10 * Created by zhengbin06 on 16/9/10.11 */
12 public classSend {13 private final static String QUEUE_NAME = "hello";14 public static void main(String[] args) throwsIOException {15 ConnectionFactory connectionFactory = newConnectionFactory();16 connectionFactory.setHost("localhost");17 //connectionFactory.setPort(5672);
18 Connection connection =connectionFactory.newConnection();19 Channel channel =connection.createChannel();20 /**
21 * Declare a queue22 *@seecom.rabbitmq.client.AMQP.Queue.Declare23 *@seecom.rabbitmq.client.AMQP.Queue.DeclareOk24 *@paramqueue the name of the queue25 * 隊列:這是這個隊列的名字26 *@paramdurable true if we are declaring a durable queue (the queue will survive a server restart)27 * 持久性:true代表聲明一個持久的隊列(服務器的重啟不會影響到隊列)28 *@paramexclusive true if we are declaring an exclusive queue (restricted to this connection)29 * 獨有性(唯一性):true代表聲明一個唯一的消息隊列(僅限于這個連接,也就是說在這個連接(通道)中這個消息隊列是唯一的)30 *@paramautoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use)31 * 自動刪除:如果為true代表聲明了一個會自動銷毀的消息隊列(當長時間不使用時,服務器將把它刪除)32 *@paramarguments other properties (construction arguments) for the queue33 * 參數:其它的一些聲明隊列的構造參數列表34 *@returna declaration-confirm method to indicate the queue was successfully declared35 *@throwsjava.io.IOException if an error is encountered36 */
37 //在這個通道中,聲明一個消息隊列
38 channel.queueDeclare(QUEUE_NAME, false, false, false, null);39 String message = "Hello World!";40 /**
41 * Publish a message42 *@seecom.rabbitmq.client.AMQP.Basic.Publish43 *@paramexchange the exchange to publish the message to44 * 交換:交換發送的消息45 *@paramroutingKey the routing key46 * 路由密鑰:代表路由的密鑰47 *@paramprops other properties for the message - routing headers etc48 * 其它信息:一些關于消息的其他屬性——路由的消息頭等49 *@parambody the message body50 * 消息主體:消息的主體(一個字節數組)51 *@throwsjava.io.IOException if an error is encountered52 */
53 channel.basicPublish("", QUEUE_NAME, null, message.getBytes());54 System.out.println(" [x] Sent '" + message + "'");55 channel.close();56 connection.close();57 }58 }
View Code
到這步為止你就可以運行Send.java 的main方法了,如果報錯或者沒有輸出,官方文檔給出的解釋是:
Sending doesn't work!
If this is your first time using RabbitMQ and you don't see the "Sent" message then you may be left scratching your head wondering what could be wrong. Maybe the broker was started without enough free disk space (by default it needs at least 1GB free) and is therefore refusing to accept messages. Check the broker logfile to confirm and reduce the limit if necessary. The configuration file documentation will show you to set disk_free_limit.
譯:如果這是你第一次使用RabbitMQ并且你沒有看到“Sent”出的消息,面對這個問題你會有點摸(yi)不(lian)到(de)頭(meng)腦(bi)。這個問題可能的原因是中間件沒有足夠的磁盤空間(默認最少需要1GB的磁盤空間),并且因此拒絕接收消息。檢查中間件(broker)的日志文件,必要時減少一些限制。配置文件中的有"disk_free_limit"這一項。
但是我并沒有遇到這個問題,在運行Send.java時遇到的是這個問題:連接被拒絕。
其實這是我們沒有RabbitMQ-Server的原因,在官方文檔的開頭就有提示:
譯:這個教程的假定你已經安裝并且運行了RabbitMQ,地址是localhost(本地)端口是5672(這個沒搞清楚,源碼顯示默認是5671,可能是我引入的版本低的原因)
點擊“installed”跳轉至如下頁面,然后選擇操作系統:
最后按照下方頁面的提示,進行安裝:
譯:下載壓縮包,解壓至任意文件夾下,解壓,在Finder中打開該包下的sbin/rabbitmq-server文件(一個shell腳本文件),或者在終端中“sbin/rabbitmq-server”也可以,Ctrl+c終止服務:
或者加上"-detached"參數,表示(in which case the server process runs in the background)也就是說這種情況下服務器在后臺運行:
查看Broker狀態:“./rabbitmqctl status”
關閉Broker:“./rabbitmqctl stop”
列出所有隊列:
你也許希望查看RabbitMQ中有哪些隊列、有多少消息在隊列中。此時你可以使用rabbitmqctl工具:
? sbin ./rabbitmqctl list_queues
這篇簡單介紹了RabbitMQ中的三個角色,和“Hello World!”這個例子中的Send.java,下面的一篇繼續完成例子中的消息消費者Recv.java。