1 "Hello World!"
Introduction(簡介)
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是一個消息代理:它接受并轉(zhuǎn)發(fā)消息。你可以將它看成是一個郵局:當你將想發(fā)送的郵件丟進郵箱時,你就可以確定郵差最終會把這封郵件送到收件人手上。通過這個類比來看,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不跟紙打交道,它只接收,存儲并轉(zhuǎn)發(fā)二進制的數(shù)據(jù)包—消息。
RabbitMQ, and messaging in general, uses some jargon.
RabbitMQ,一般稱它為消息隊列,它使用了一些術(shù)語。
Producing means nothing more than sending. A program that sends messages is a producer:
消息生產(chǎn)其實就是消息發(fā)送。發(fā)送消息的程序就是生產(chǎn)者:

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內(nèi)部的郵箱。雖然消息在傳遞時是流經(jīng)RabbitMQ和你的應(yīng)用,但它們只能被存儲在某個隊列里。隊列大小只受限于主機內(nèi)存和硬盤容量,它本質(zhì)上就是個大的消息緩存。多個生產(chǎn)者可以往一個隊列里發(fā)送消息,多個消費者可以從一個隊列里獲取數(shù)據(jù)。以下是我們表示一個隊列的方式:

Consuming has a similar meaning to receiving. A consumer is a program that mostly waits to receive messages:
消息消費其實就是消息接收。等待接收消息的程序就是一個消費者:

Note that the producer, consumer, and broker do not have to reside on the same host; indeed in most applications they don't.
注意,生產(chǎn)者,消費者和代理不一定都在同一個主機里;實際上,在大多數(shù)應(yīng)用中,這三者都不是在同一個主機里。
"Hello World"
In this part of the tutorial we'll write two programs using the spring-amqp library; 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 Spring-amqp API, concentrating on this very simple thing just to get started. It's a "Hello World" of messaging.
在本教程里,我們將寫兩個基于spring-amqp類庫的程序,其中一個是發(fā)送單條消息的生產(chǎn)者,另一個是消費者,它接收消息并將它們打印出來。我們將省略Spring-amqp API的一些細節(jié),專注于即將開始的東西。它是消息隊列版本的“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”是我們的生產(chǎn)者,“C”是我們的消費者。圖中間的箱子是一個隊列,也就是RabbitMQ給消費者用的的消息緩存:

The Spring AMQP Framework(Spring AMQP框架)
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.
RabbitMQ支持多種協(xié)議。本教程使用AMQP 0-9-1協(xié)議,它是一個開放,通用的消息隊列協(xié)議。很多編程語言都提供了RabbitMQ客戶端。
Spring AMQP leverages Spring Boot for configuration and dependency management. Spring supports maven or gradle but for this tutorial we'll select maven with Spring Boot 1.5.2. Open the Spring Initializr and provide: the group id (e.g. org.springframework.amqp.tutorials) the artifact id (e.g. rabbitmq-amqp-tutorials). Search for the amqp dependency and select the AMQP dependency.
Spring AMQP利用Spring Boot來進行配置和依賴管理。Spring同時支持maven或者gradle,但在本教程里我們選擇用maven,同時采用Spring Boot 1.5.2版本。我們打開Spring Initializr并提供group id(如org.springframework.amqp.tutorials)和artifact id(如rabbitmq-amqp-tutorials)。查找amqp依賴并選擇AMQP依賴。(譯者注:應(yīng)該是搜索rabbitmq)
Generate the project and unzip the generated project into the location of your choice. This can now be imported into your favorite IDE. Alternatively you can work on it from your favorite editor.
點擊Generate Project生成項目,下載并將其解壓到你想存放的目錄?,F(xiàn)在你可以在你喜歡的IDE里面導(dǎo)入這個項目。你也可以在你喜歡的編輯器上進行下一步編輯。
Configuring the project(配置項目)
Spring Boot offers numerous features but we will only highlight a few here. First, Spring Boot applications have the option of providing their properties through either an application.properties or application.yml file (there are many more options as well but this will get us going). You'll find an application.properties file in the generated project with nothing in it. Rename application.properties to application.yml file with the following properties:
Spring Boot提供了很多特性,但在這里我們只顯示幾個需要用到的。首先,Spring Boot應(yīng)用的配置可以寫在application.properties文件或者application.yml文件里(還有許多其它的方式,但對于我們,用這兩種文件就足夠了)。你在生成的項目里將會找到一個空的application.properties文件。將這個文件重命名為application.yml,并寫上這些屬性:
spring:
profiles:
active: usage_message
logging:
level:
org: ERROR
tutorial:
client:
duration: 10000
Create a new directory (package - tut1) where we can put the tutorial code. We'll now create a JavaConfig file (Tut1Config.java) to describe our beans in the following manner:
創(chuàng)建一個新的目錄(package - tut1)用來放我們的教程代碼?,F(xiàn)在我們將通過以下方式創(chuàng)建一個Java配置文件(Tut1Config.java)來描述我們的Bean:
package org.springframework.amqp.tutorials.tut1;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Profile({"tut1","hello-world"})
@Configuration
public class Tut1Config {
@Bean
public Queue hello() {
return new Queue("hello");
}
@Profile("receiver")
@Bean
public Tut1Receiver receiver() {
return new Tut1Receiver();
}
@Profile("sender")
@Bean
public Tut1Sender sender() {
return new Tut1Sender();
}
}
Note that we've defined the 1st tutorial profile as either tut1, the package name, or hello-world. We use the @Configuration to let Spring know that this is a Java Configuration and in it we create the definition for our Queue ("hello") and define our Sender and Receiver beans.
注意,我們已經(jīng)將教程的第一個配置組定義為tu1(即報名),或者hello-world。我們用@Configuration注解來讓Spring知道這是個Java配置,并且在配置里我們定義了隊列Queue("hello"),而且也定義了我們的發(fā)送者和接收者。
We will run all of our tutorials through the Boot Application now by simply passing in which profiles we are using. To enable this we will modify the generated RabbitAmqpTutorialsApplication.java with the following:
現(xiàn)在我們將傳入需要用到配置組,通過Boot Application來運行我們的教程。為了做到這一點,我們將修改生成的RabbitAmqpTutorialsApplication.java文件,如下所示:
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class RabbitAmqpTutorialsApplication {
@Profile("usage_message")
@Bean
public CommandLineRunner usage() {
return new CommandLineRunner() {
@Override
public void run(String... arg0) throws Exception {
System.out.println("This app uses Spring Profiles to control its behavior.\n");
System.out.println("Sample usage: java -jar rabbit-tutorials.jar --spring.profiles.active=helloworld,sender");
}
};
}
@Profile("!usage_message")
@Bean
public CommandLineRunner tutorial() {
return new RabbitAmqpTutorialsRunner();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(RabbitAmqpTutorialsApplication.class, args);
}
}
and add the RabbitAmqpTutorialsRunner.java code as follows:
然后像下面那樣添加RabbitAmqpTutorialsRunner.java代碼:
package org.springframework.amqp.tutorials;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;
public class RabbitAmqpTutorialsRunner implements CommandLineRunner {
@Value("${tutorial.client.duration:0}")
private int duration;
@Autowired
private ConfigurableApplicationContext ctx;
@Override
public void run(String... arg0) throws Exception {
System.out.println("Ready ... running for " + duration + "ms");
Thread.sleep(duration);
ctx.close();
}
}
Sending(發(fā)送)

Now there is very little code that needs to go into the sender and receiver classes. Let's call them Tut1Receiver and Tut1Sender. The Sender leverages our config and the RabbitTemplate to send the message.
現(xiàn)在發(fā)送者類和接收者類需要寫的代碼很少。我們把接收者的類名叫做Tut1Receiver,把發(fā)送者的類名叫做Tut1Sender。發(fā)送者類利用我們的配置和RabbitTemplate類來發(fā)送消息。
// Sender
package org.springframework.amqp.tutorials.tut1;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
public class Tut1Sender {
@Autowired
private RabbitTemplate template;
@Autowired
private Queue queue;
@Scheduled(fixedDelay = 1000, initialDelay = 500)
public void send() {
String message = "Hello World!";
this.template.convertAndSend(queue.getName(), message);
System.out.println(" [x] Sent '" + message + "'");
}
}
You'll notice that spring-amqp removes the boiler plate code leaving you with only the logic of the messaging to be concerned about. We autowire in the queue that was configured in our bean definition in the Tut1Config class and like many spring connection abstractions, we wrap the boilerplate rabbitmq client classes with a RabbitTemplate that can be autowired into the sender. All that is left is to create a message and invoke the template's convertAndSend method passing in the queue name from the bean we defined and the message we just created.
你會發(fā)覺,spring-amqp移除了樣板化代碼,讓你只專注于消息發(fā)送邏輯。我們自動注入了隊列queue,它已經(jīng)在前面的Tut1Config類里做了配置。就像大多數(shù)Spring連接抽象,我們用RabbitTemplate包裝了樣板化的rabbitmq客戶端類,并將它自動注入到發(fā)送者類里。我們要做的就是創(chuàng)建一條信息,并調(diào)用template的convertAndSend方法,傳入我們定義的隊列bean的名字以及我們剛創(chuàng)建的信息。
Sending doesn't work!(無法發(fā)送?。?/h4>
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并且你看不到打印出來的“Sent”消息,你可能會在那里苦惱著哪里出錯了。也許消息代理在啟動時不夠磁盤空間(默認它需要200MB的空間),由此導(dǎo)致拒絕接收信息。如有必要,檢查代理的日志文件來確認并減少所需最小磁盤空間的限制。配置文件文檔里會告訴你如何設(shè)置disk_free_limit(最小所需磁盤空間)參數(shù)
Receiving(接收)
The receiver is equally simple. We annotate our Receiver class with @RabbitListener and pass in the name of the queue. We then annotate our receive method with @RabbitHandler passing in the payload that has been pushed to the queue.
接收者類很簡單。我們用@RabbitListener來注解我們的接收者類,并往注解里傳入隊列的名字。然后我們用@RabbitHandler來注解我們的接收方法,接收的參數(shù)為推入隊列里的負載。
package org.springframework.amqp.tutorials.tut1;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
@RabbitListener(queues = "hello")
public class Tut1Receiver {
@RabbitHandler
public void receive(String in) {
System.out.println(" [x] Received '" + in + "'");
}
}
Putting it all together(代碼整合)
The app uses Spring Profiles to control what tutorial it's running, and whether it's a Sender or Receiver. Choose which tutorial to run by using the profile. For example:
程序通過使用Spring配置組來控制正在運行的是哪個教程代碼,以及控制正在運行的是發(fā)送者還是接收者。我們選擇使用不同的配置組來運行不同的教程代碼。例如:
- {tut1|hello-world},{sender|receiver}
- {tut2|work-queues},{sender|receiver}
- {tut3|pub-sub|publish-subscribe},{sender|receiver}
- {tut4|routing},{sender|receiver}
- {tut5|topics},{sender|receiver}
- {tut6|rpc},{client|server}
We'll come back to this list as we progress through the other five tutorials. After building with maven, run the app however you like to run boot apps (e.g. from the ide, or command line). We'll show how to run from the command line.
涉及到其它五個教程時我們還會回來參照這個列表。用maven構(gòu)建完后,你可以用你喜歡的方式來運行程序(例如,通過ide或通過命令行)。我們將展示如何通過命令行來運行。
For example(例如):
# publisher
java -jar rabbitmq-tutorials.jar --spring.profiles.active=hello-world,sender
# consumer
java -jar rabbitmq-tutorials.jar --spring.profiles.active=hello-world,receiver
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工具來查看(但你必須是個授權(quán)用戶):
sudo rabbitmqctl list_queuesOn Windows, omit the sudo:
在Windows系統(tǒng)上,輸入命令時要去掉sudo:
rabbitmqctl.bat list_queues
Time to move on to part 2 and build a simple work queue.
接下來我們開始教程的第2部份,并構(gòu)建一個簡單的工作隊列。
轉(zhuǎn)自我的博客:https://jiapengcai.github.io/posts/53264/