天天看點

RabbitMQ官方文檔翻譯之Simple(一)Introduction

Introduction

Prerequisites(先決條件)

This tutorial assumes RabbitMQ is installed and running on localhost on standard port (5672). In case you use a different host, port or credentials, connections settings would require adjusting.

本教程假定RabbitMQ已在标準端口(5672)上的localhost上安裝并運作。如果使用不同的主機,端口或憑據,下列代碼中關于連接配接設定将需要調整。

RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. Postman will eventually deliver the mail to your recipient. In this analogy, RabbitMQ is a post box, a post office and a postman.

RabbitMQ是一個消息代理:它接受并轉發消息。 您可以将其視為郵局:當您将要把寄發的郵件投遞到郵箱中時,您可以确信Postman 先生最終會将郵件發送給收件人。 在這個比喻中,RabbitMQ是一個郵箱,郵局和郵差。

The major difference between RabbitMQ and the post office is that it doesn’t deal with paper, instead it accepts, stores and forwards binary blobs of data ‒ messages.

RabbitMQ和郵局之間的主要差別在于它不處理紙張,而是接受,存儲和轉發二進制資料塊的消息。

RabbitMQ, and messaging in general, uses some jargon.

RabbitMQ和消息傳遞一般使用一些術語。

Producing means nothing more than sending. A program that sends messages is a producer :

生産意味着什麼不僅僅是發送。 發送消息的程式是一個生産者:
RabbitMQ官方文檔翻譯之Simple(一)Introduction

A queue is the name for a post box which lives inside RabbitMQ. Although messages flow through RabbitMQ and your applications, they can only be stored inside a queue. A queue is only bound by the host’s memory & disk limits, it’s essentially a large message buffer. Many producers can send messages that go to one queue, and many consumers can try to receive data from one queue. This is how we represent a queue:

隊列就像是在RabbitMQ中扮演郵箱的角色。 雖然消息流過RabbitMQ和您的應用程式,但它們隻能存儲在隊列中。 隊列隻受主機的記憶體和磁盤限制的限制,它本質上是一個大的消息緩沖區。 許多生産者可以發送到一個隊列的消息,許多消費者可以嘗試從一個隊列接收資料。 這是我們如何代表一個隊列:
RabbitMQ官方文檔翻譯之Simple(一)Introduction

Consuming has a similar meaning to receiving. A consumer is a program that mostly waits to receive messages:

消費具有與接收相似的含義。消費者是主要是一個等待接收消息的程式:
RabbitMQ官方文檔翻譯之Simple(一)Introduction

Note that the producer, consumer, and broker do not have to reside on the same host; indeed in most applications they don’t.

請注意,producer,consumer和broker(rabbitMQ server)不必駐留在同一個主機上;确實在大多數應用程式中它們是這樣分布的。

“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.

在本教程的這一部分,我們将用Java編寫兩個程式; 發送單個消息的生産者,以及接收消息并将其列印出來的消費者。 我們将介紹Java API中的一些細節,專注于這個非常簡單的事情,隻需要開始。 這是一個“Hello World”的消息傳遞。

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.

在下圖中,“P”是我們的生産者,“C”是我們的消費者。 中間的框是隊列 - RabbitMQ代表消費者的消息緩沖區。
RabbitMQ官方文檔翻譯之Simple(一)Introduction

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 and its dependencies (SLF4J API and SLF4J Simple). Copy those files in your working directory, along the tutorials Java files.

Please note SLF4J Simple is enough for tutorials but you should use a full-blown logging library like Logback in production.

(The RabbitMQ Java client is also in the central Maven repository, with the groupId com.rabbitmq and the artifactId amqp-client.)

Java用戶端庫

RabbitMQ講多種協定。 本教程使用AMQP 0-9-1,它是一種開放的通用的用于消息傳遞的協定。 有許多不同語言的RabbitMQ用戶端。 我們将使用RabbitMQ提供的Java用戶端。

下載下傳用戶端庫及其依賴項(SLF4J API和SLF4J Simple)。 複制這些到你的工作目錄中得僅僅是教程列舉的java檔案,依賴需要你自己添加。

請注意SLF4J 對于教程簡單就足夠了,但您應該使用成熟的日志庫,如Logback。

(RabbitMQ Java用戶端也位于Maven中央存儲庫中,groupId = com.rabbitmq 和 artifactId = amqp-client。)

Now we have the Java client and its dependencies, we can write some code.

現在我們有了java用戶端和它的依賴,我們就可以寫下面的代碼

Sending (發送端)

RabbitMQ官方文檔翻譯之Simple(一)Introduction

We’ll call our message publisher (sender) Send and our message consumer (receiver) Recv. The publisher will connect to RabbitMQ, send a single message, then exit.

我們可以通知我們的消息釋出者(發件人)發送和我們的消息消費者(接收者)Recv。釋出商将連接配接到RabbitMQ,發送單個消息,然後退出。

In Send.java, we need some classes imported:

在Send.java中,我們需要一些導入的類
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
           

Set up the class and name the queue:

設定類并命名隊列
public class Send {
  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv)
      throws java.io.IOException {
      ...
  }
}
           

then we can create a connection to the server:

那麼我們可以建立一個到伺服器的連接配接:
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
           

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 the localhost. 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:

這個connection抽象的當做是套接字連接配接 socket connection,并對我們進行協定版本協商和認證等。 在這裡,我們連接配接到本地機器上的代理 - 是以填localhost。 如果我們想連接配接到不同機器上的broker,我們可以在此處指定它的名稱或IP位址。

接下來,我們建立一個通道channel,這是通過調用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.

這是整個Send.java類。

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 200 MB 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 how to set disk_free_limit.

如果這是您第一次使用RabbitMQ,并且沒有看到“已發送”消息,那麼您可能會很郁悶,可能認為他有錯誤。 或許是broker沒有足夠的可用磁盤空間啟動(預設情況下至少需要200 MB),是以它拒絕接受message。 檢查broker日志檔案以确認并減少限制(如有必要)。 配置檔案文檔将顯示如何設定disk_free_limit。

Receiving(接收)

That’s it for our publisher. Our consumer is pushed messages from RabbitMQ, so unlike the publisher which publishes a single message, we’ll keep it running to listen for messages and print them out.

上面說的就是publisher。消費者将接收到來自RabbitMQ推送的消息,它不同于釋出單個消息的釋出者,我們将保持它持續運作來監聽消息并列印出來。
RabbitMQ官方文檔翻譯之Simple(一)Introduction

The code (in Recv.java) has almost the same imports as Send:

Recv.java 幾乎和Send.java導入的jar包是一樣的

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;
           

The extra DefaultConsumer is a class implementing the Consumer interface we’ll use to buffer the messages pushed to us by the server.

額外導入的DefaultConsumer是一個實作Consumer接口的類,用于緩沖由伺服器推送給我們的消息

Setting up is the same as the publisher; we open a connection and a channel, and declare the queue from which we’re going to consume. Note this matches up with the queue that send publishes to.

代碼也與publisher的相同;我們new一個連接配接和create一個通道,并聲明我們要消費的隊列。注意這裡申明的隊列要和發送的消息隊列一緻。
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");
    ...
    }
}
           

Note that we declare the queue here, as well. Because we might start the consumer before the publisher, we want to make sure the queue exists before we try to consume messages from it.

請注意,我們也在這裡聲明隊列并不是必須的。但是我們可能會在publisher之前啟動消費者,是以我們要確定隊列存在,然後再嘗試從中消費消息

We’re about to tell the server to deliver us the messages from the queue. Since it will push us messages asynchronously, we provide a callback in the form of an object that will buffer the messages until we’re ready to use them. That is what a DefaultConsumer subclass does.

我們還要告訴伺服器将隊列中的消息傳遞給我們。 由于它會異步地推送給我們的message,是以我們提供一個對象形式的回調,該對象将緩沖消息,直到我們準備好使用它們。 這是一個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);
           

Here’s the whole Recv.java class.(這裡就是整個Recv.java)

Putting it all together

You can compile both of these with just the RabbitMQ java client on the classpath:

//把他們放在一起,我們可以在包含RabbitMQ java的類路徑下編譯它們 

javac -cp amqp-client-.jar Send.java Recv.java
To run them, you'll need rabbitmq-client.jar and its dependencies on the classpath. In a terminal, run the consumer (receiver):

java -cp .:amqp-client-.jar:slf4j-api-.jar:slf4j-simple-.jar Recv
then, run the publisher (sender):

java -cp .:amqp-client-.jar:slf4j-api-.jar:slf4j-simple-.jar Send
On Windows, use a semicolon instead of a colon to separate items in the classpath.
           

The consumer will print the message it gets from the publisher via RabbitMQ. The consumer will keep running, waiting for messages (Use Ctrl-C to stop it), so try running the publisher from another terminal.

消費者将通過RabbitMQ列印從釋出商獲得的消息。消費者将繼續運作,等待消息(使用Ctrl-C停止它),是以嘗試從另一個終端運作釋出者

Listing queues

You may wish to see what queues RabbitMQ has and how many messages are in them. You can do it (as a privileged user) using the rabbitmqctl tool:

您可能希望看到RabbitMQ有什麼隊列和其中有多少個消息。您可以使用rabbitmqctl工具(作為特權使用者)

On Linux

sudo rabbitmqctl list_queues
           

On Windows, omit the sudo:

rabbitmqctl.bat list_queues
           

Time to move on to part 2 and build a simple work queue.

Hint

To save typing, you can set an environment variable for the classpath e.g.

>export CP=.:amqp-client-.jar:slf4j-api-.jar:slf4j-simple-.jar
>java -cp $CP Send
           
or on Windows:
set CP=.;amqp-client-.jar;slf4j-api-.jar;slf4j-simple-.jar
java -cp %CP% Send
           

http://www.rabbitmq.com/img/tutorials/producer.png