RabbitMQ是消息代理。从本质上说,它接受来自生产者的信息,并将它们传递给消费者。在两者之间,它可以根据你给它的路由,缓冲规则进行传递消息。
如果你的工作中需要用到RabbitMQ,那么我建议你先在电脑上安装好RabbitMQ服务器,然后打开eclipse,跟这我的教程一步步的学习RabbitMQ,这样你会对RabbitMQ有一个全面的认识,而且能打好一个很好的基础。如果你只是了解一下,那就随便看看吧。
一、专业术语
1. 生产者:
在现实生活中就好比制造商品的工厂,他们是商品的生产者。生产者只意味着发送。发送消息的程序称之为一个生产者。我们用“P”表示:
2. 队列:
队列就像存放商品的仓库或者商店,是生产商品的工厂和购买商品的用户之间的中转站。队列就像是一个仓库或者流水线。在RabbitMQ中,信息流从你的应用程序出发,来到RabbitMQ的队列,所有信息可以只存储在一个队列中。队列可以存储很多的消息,因为它基本上是一个无限制的缓冲区,前提是你的机器有足够的存储空间。多个生产者可以将消息发送到同一个队列中,多个消费者也可以只从同一个队列接收数据。这就是队列的特性。队列用下面的图表示,图上面是队列的名字:
3. 消费者
消费者就好比是从商店购买或从仓库取走商品的人,消费的意思就是接收。消费者是一个程序,主要是等待接收消息。我们的用“C”表示
注意:
生产者,消费者和队列(RabbitMQ)不必部署在同一台机器上。实际在生产环境的大多数应用中,他们都是分开部署的。
二、“Hello World”
1. 说明
在本教程中,我们我们通过2个java程序,一个发送消息的生产者,和一个接收信息并打印的消费者。想要了解rabbitmq,必须了解一些最基础的内容,我们先从一些代码片段来了解产生信息和接收消息的流程和方法。在编写代码前,我们先来用户一张图表示要做的事,在下图中,“P”是我们的生产者,“C”是我们的消费者。在中间红色框是代表RabbitMQ中的一个消息队列。箭头指向表示信息流的方向。
2. 项目目录
在eclipse中创建一个rabbitmq的java项目,然后在项目下建一个名为lib的source folder, 然后将rabbitmq官网下载的rabbitmq-java-client-bin-3.6.0.rar解压出rabbitmq-client.jar拷贝到lib目录,如果创建的是Maven项目,只需要添加如下依赖:
[plain] view plain copy
1. <dependencies>
2. <dependency>
3. <groupId>com.rabbitmq</groupId>
4. <artifactId>amqp-client</artifactId>
5. <version>3.6.0</version>
6. </dependency>
7. ... ...
8. </dependencies>
然后在src目录下创建一个com.aitongyi.rabbit.helloworld包,最后项目目录如下:
3. 消息生产者
[plain] view plain copy
1. import com.rabbitmq.client.Channel;
2. import com.rabbitmq.client.Connection;
3. import com.rabbitmq.client.ConnectionFactory;
4.
5. /**
6. * 消息生产者
7. *
8. * @author hushuang
9. *
10. */
11. public class P {
12.
13. private final static String QUEUE_NAME = "hello";
14.
15. public static void main(String[] argv) throws Exception {
16. // 创建连接工厂
17. ConnectionFactory factory = new ConnectionFactory();
18. // 设置RabbitMQ地址
19. factory.setHost("localhost");
20. // 创建一个新的连接
21. Connection connection = factory.newConnection();
22. // 创建一个频道
23. Channel channel = connection.createChannel();
24. // 声明一个队列 -- 在RabbitMQ中,队列声明是幂等性的(一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同),也就是说,如果不存在,就创建,如果存在,不会对已经存在的队列产生任何影响。
25. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
26. String message = "Hello World!";
27. // 发送消息到队列中
28. channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
29. System.out.println("P [x] Sent '" + message + "'");
30. // 关闭频道和连接
31. channel.close();
32. connection.close();
33. }
34. }
4. 消息消费者
[plain] view plain copy
1. import com.rabbitmq.client.*;
2. import java.io.IOException;
3.
4. /**
5. * 消息消费者
6. *
7. * @author hushuang
8. *
9. */
10. public class C {
11.
12. private final static String QUEUE_NAME = "hello";
13.
14. public static void main(String[] argv) throws Exception {
15. // 创建连接工厂
16. ConnectionFactory factory = new ConnectionFactory();
17. // 设置RabbitMQ地址
18. factory.setHost("localhost");
19. // 创建一个新的连接
20. Connection connection = factory.newConnection();
21. // 创建一个频道
22. Channel channel = connection.createChannel();
23. // 声明要关注的队列 -- 在RabbitMQ中,队列声明是幂等性的(一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同),也就是说,如果不存在,就创建,如果存在,不会对已经存在的队列产生任何影响。
24. channel.queueDeclare(QUEUE_NAME, false, false, false, null);
25. System.out.println("C [*] Waiting for messages. To exit press CTRL+C");
26. // DefaultConsumer类实现了Consumer接口,通过传入一个频道,告诉服务器我们需要那个频道的消息,如果频道中有消息,就会执行回调函数handleDelivery
27. Consumer consumer = new DefaultConsumer(channel) {
28. @Override
29. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
30. String message = new String(body, "UTF-8");
31. System.out.println("C [x] Received '" + message + "'");
32. }
33. };
34. // 自动回复队列应答 -- RabbitMQ中的消息确认机制,后面章节会详细讲解
35. channel.basicConsume(QUEUE_NAME, true, consumer);
36. }
37. }
5. 运行测试
如果在windows7下,你需要先双击【RabbitMQ Server\rabbitmq_server-3.6.0\sbin】目录下的rabbitmq-server.bat,来启动RabbitMQ服务。负责,运行我们的程序时,会提示【java.net.ConnectException: Connection refused: connect】
C [*] Waiting for messages. To exit press CTRL+CC[x] Received 'Hello World!'
先运行消费者服务器来关注【hello】这个队列的情况。
[plain] view plain copy
1. C [*] Waiting for messages. To exit press CTRL+C
C [*] Waiting for messages. To exit press CTRL+CC[x] Received 'Hello World!'
然后再运行生产者端,发送消息到队列中:
[plain] view plain copy
1. P [x] Sent 'Hello World!'
C [*] Waiting for messages. To exit press CTRL+CC[x] Received 'Hello World!'
再切换到消费者端的控制台,查看日志:
[plain] view plain copy
1. C [*] Waiting for messages. To exit press CTRL+C
2. C [x] Received 'Hello World!'