RabbitMQ 学习笔记(一):简单介绍及"Hello World"
2017-07-13 20:13
666 查看
RabbitMQ 简单介绍:
RabbitMQ是一个消息代理,即它的功能为:接受和转发消息。你可以把它想象成一个邮局:当你把你想要的邮件放在邮箱里,你可以肯定邮差先生最终会把邮件送到你的收件人那里。在这个类比中,RabbitMQ相当于一个邮筒、一个邮局和一个邮差。
RabbitMQ与邮局的主要区别在于,它不处理纸张,而是接受、存储和转发数据的二进制数据。
RabbitMQ和一般的消息传递使用到一些术语:
生产( producing)意味着发送消息。发送消息的程序是生产者( producer ):
队列( queue)是在RabbitMQ内的一个邮箱的名称。尽管消息通过RabbitMQ和您的应用程序流,但它们只能存储在队列中。队列仅由主机的内存和磁盘限制绑定,它本质上是一个大的消息缓冲(buffer)。许多生产者可以发送到一个队列的消息,许多用户可以尝试从一个队列接收数据。这就是我们如何表示一个队列:
消费( consuming)也有类似的含义。消费者( consumer)是一个主要等待接收消息的程序:
请注意,生产者、使用者和代理(broker)不必驻留在同一主机( host )上 。实际上在大多数应用程序中,它们不需要驻留在同一主机上。
简单的应用 — “Hello World!”
在本教程中,我们将在Java中编写两个程序 : 一个发送单个消息的生成器,以及接收消息并将其打印出来的使用者。我们将对Java API中的一些细节进行粉饰,将注意力集中在这个非常简单的事情上。这只是一个“Hello World”的消息传递。
在下面的简化图中,“P”是我们的生产者,“C”是我们的消费者。
中间的框是一个队列——RabbitMQ代表消费者保存的消息缓冲区。
这里需要顺便提一下Java客户端库( the Java cilent library ):
RabbitMQ讲多种协议。本教程使用AMQP 0 - 9 - 1,这是一种开放的、通用的消息传递协议。有许多不同语言的RabbitMQ客户。我们将使用RabbitMQ提供的Java客户机。下载客户端库(client library)及其依赖关系(SLF4J API 和SLF4J Simple)。将这些文件以及教程Java文件,复制到您的工作目录中。
请注意,SLF4J Simple就足够用于教程,但是您应该使用一个成熟的日志库,如在生产中的Logback。(带有标识符com.rabbitmq和名字 amqp - client的RabbitMQ Java客户机,也在中央Maven存储库中。)
现在有了Java客户端库及其依赖关系,我们可以开始编写代码。
生产者发送消息:
我们将称呼我们的消息发布者(publisher)为 Send 和我们的消息接收者(或者消费者)为 Recv 。Send 将连接到RabbitMQ,发送一条消息,然后退出。
首先,在Send.java中,我们需要import一些类:
import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.Connection; import com.rabbitmq.client.Channel;
创建Send类,给队列queue命名。
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();
这里我们连接到本地机器上的一个代理——本地主机(localhost)。如果我们想要连接到另一台机器上的代理,我们只需在这里指定它的名称或IP地址。然后,我们创建了一个channel,它是用于完成大部分任务的API。为了发送消息,我们必须声明一个queue供我们发送,然后我们就可将消息发布到queue:
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 + "'");
声明队列queue是幂等的——它只会在不存在的情况下创建。消息内容是一个byte数组,因此你可以以任何你喜欢的方式进行编码。
最后,我们关闭连接和channel:
channel.close(); connection.close();
这里是完整的Send.class:
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + message + "'");
channel.close(); connection.close();
}
}
注意:如果这是你第一次使用RabbitMQ,而你没有看到“发送”消息。这可能是代理开始时没有足够的空闲磁盘空间(默认情况下,它至少需要200 MB),因此拒绝接受消息。检查代理日志文件以确认并减少必要的限制。配置文件文档将显示如何设置disk_free_limit。
消费者接收信息:
我们的消费者需要获取来自RabbitMQ的消息,所以不同于发布单一消息的发布者,我们将保持消费者运行以侦听消息并将其打印出来。
首先,同理,我们需要import一些类:
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接口的类,我们将使用它来缓冲服务器向我们推送的消息。
接下来的设置与 Send 相同。我们打开一个连接和一个channel,并声明我们将要使用的队列queue。
请注意,这里声明的queue与Send发布消息到的queue相匹配(声明的各参数相同)。
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");
...
}
}
注意,这里也声明了queue(而不是直接调用)。因为我们可能在发布者之前启动消费者,所以我们应该保证在尝试使用它之前,确保queue存在。
我们将告诉服务器将消息从queue传递给我们。由于它将异步推送消息,所以我们提供一个对象的形式的回调,它将对消息进行缓冲,直到我们准备好使用它们为止。这就是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);
这里是完整的Recv.java:
import com.rabbitmq.client.*;
import java.io.IOException;
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
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");
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 client来编译这两个类:
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
最后,你可能希望看到RabbitMQ有哪些队列,以及其中有多少消息。可以使用rabbitmqctl工具(要有root权限)以获得相关信息:
sudo rabbitmqctl list_queues
为了简化每一次的编译执行命令,你可以为类路径设置一个环境变量
export CP=.:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar
//设置环境变量
java -cp $CP Send
//简化编译执行命令
相关链接
rabbitmq-c++(SimpleAmqpClient) 笔记代码系列:rabbitmq-c++(SimpleAmqpClient) 笔记代码一
rabbitmq-c++(SimpleAmqpClient) 笔记代码二
rabbitmq-c++(SimpleAmqpClient) 笔记代码三
rabbitmq-c++(SimpleAmqpClient) 笔记代码四
rabbitmq-c++(SimpleAmqpClient) 笔记代码五
rabbitmq-c++(SimpleAmqpClient) 笔记代码六
RabbitMQ 学习笔记系列:
RabbitMQ 学习笔记(一):简单介绍及”Hello World”
RabbitMQ 学习笔记(二):work queues
RabbitMQ 学习笔记(三):Publish/Subscribe
RabbitMQ 学习笔记(四):Routing
RabbitMQ 学习笔记(五):Topics
RabbitMQ 学习笔记(六):RPC
相关文章推荐
- WTL学习笔记——(2)WTL Hello World !
- pthread学习笔记(二)--pthread常用API及简单介绍
- iOS学习笔记14(1)—Core Data简单介绍和实现
- Nutch 1.3 学习笔记 10-1 - Ntuch 插件机制简单介绍
- anroid JNI 学习笔记 最简单的Hello
- 【实验】【PROCEDURE】一个最简单的oracle存储过程"proc_helloworld"【转】
- 【实验】【PROCEDURE】一个最简单的oracle存储过程"proc_helloworld"
- 韩顺平_轻松搞定网页设计(html+css+javascript)_第19讲_js运行原理_js开发工具介绍_js程序(hello)_js基本语法_学习笔记_源代码图解_PPT文档整理
- ICE第二篇--一个"hello world"的简单例子
- linux & C++Primer 学习笔记--预处理器的简单介绍
- Linux设备驱动程序学习(0) -设备驱动介绍& Hello, world!模块
- Nutch 1.3 学习笔记 10-1 - Ntuch 插件机制简单介绍
- [每日学习笔记][2013.03.24]MYSQL的语法和简单介绍(二)
- 一个简单的"Hello World"
- Linux设备驱动程序学习(0) -设备驱动介绍& Hello, world!模块
- Apache Nutch 1.3 学习笔记十(Ntuch 插件机制简单介绍)
- .Linux设备驱动程序学习(0)——设备驱动介绍& Hello, world!模块 内核参数传递
- Java学习笔记2 —— Hello World
- wxWidget学习笔记二:Hello World!
- hello_world-2.2之简单设备驱动模型(二)---device,bus,driver结构介绍