RabbitMQ (一) 入门
消息队列有很多种,每个都有各自的特性,都有自己的使用场景。
消息中间件部署及比较:rabbitMQ、activeMQ、zeroMQ、rocketMQ、Kafka、redis
介绍
RabbitMQ 是一个消息代理。它的核心原理非常简单:接收和发送消息。你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处。在这个比喻中,RabbitMQ 就扮演着邮箱、邮局以及邮递员的角色。
RabbitMQ 和邮局的主要区别是,它不是用来处理纸张的,它是用来接收、存储和发送消息(message)这种二进制数据的。
一般提到 RabbitMQ 和消息,都会用到一些专有名词。
- 生产(Producing)意思就是发送。发送消息的程序就是一个生产者(producer)。我们一般用 “P” 来表示:
[外链图片转存失败(img-EQKcr4uB-1568874186376)(http://wiki.jikexueyuan.com/project/rabbitmq/images/1.png)]
- 队列(queue)就是邮箱的名称。消息通过你的应用程序和 RabbitMQ 进行传输,它们能够只存储在一个队列(queue)中。 队列(queue)没有任何限制,你要存储多少消息都可以——基本上是一个无限的缓冲。多个生产者(producers)能够把消息发送给同一个队列,同样,多个消费者(consumers)也能够从同一个队列(queue)中获取数据。队列可以绘制成这样(图上是队列的名称):
-
消费(Consuming)和获取消息是一样的意思。一个消费者(consumer)就是一个等待获取消息的程序。我们把它绘制为 “C”:
需要指出的是生产者、消费者、代理需不要待在同一个设备上;事实上大多数应用也确实不在会将他们放在一台机器上。
安装RabbitMQ
我是直接安装到远程服务器的docker上的。
-
下载镜像:
docker pull rabbitmq:3.7.7-management
-
运行容器:
docker run -d -p 5671:5617 -p 5672:5672 -p 4369:4369 -p 15671:15671 -p 15672:15672 -p 25672:25672 --name rabbit-3.7.7 -v /var/lib/rabbitmq:/var/lib/rabbitmq rabbitmq:3.7.7-management
-
进入容器:
docker exec -it rabbit-3.7.7 /bin/bash
-
给容器安装 下载工具 wget:
apt-get install -y wget
-
下载插件包,因为我们的
RabbitMQ
版本为3.7.7
所以我们安装3.7.x
版本的延迟队列插件root@f72ac937f2be:/plugins# wget https://dl.bintray.com/rabbitmq/community-plugins/3.7.x/rabbitmq_delayed_message_exchange/rabbitmq_delayed_message_exchange-20171201-3.7.x.zip
-
给容器安装 解压工具 unzip:
apt-get install -y unzip
-
解压插件包
root@f72ac937f2be:/plugins# unzip rabbitmq_delayed_message_exchange-20171201-3.7.x.zip Archive: rabbitmq_delayed_message_exchange-20171201-3.7.x.zip inflating: rabbitmq_delayed_message_exchange-20171201-3.7.x.ez
-
启动延迟队列插件
root@f72ac937f2be:/plugins# rabbitmq-plugins enable rabbitmq_delayed_message_exchange The following plugins have been configured: rabbitmq_delayed_message_exchange rabbitmq_management rabbitmq_management_agent rabbitmq_web_dispatch Applying plugin configuration to rabbit@f72ac937f2be... The following plugins have been enabled: rabbitmq_delayed_message_exchange started 1 plugins.
-
退出容器:
exit
-
停止容器:
docker stop rabbit-3.7.7
-
启动容器:
docker start rabbit-3.7.7
入门demo
创建发送端:
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 发送端
*/
public class Send
{
private final static String QUEUE_NAME = "hello";
public static void main(String[] args)
{
// 创建连接池 AMQP模型
ConnectionFactory factory = new ConnectionFactory();
// 服务器地址
factory.setHost("120.79.XXX.XXX");
try
{
// 创建连接
Connection connection = factory.newConnection();
// 获取通道
Channel channel = connection.createChannel();
/**
* queueDeclare 队列声明
* queueDeclare(String queue,
* boolean durable,
* boolean exclusive,
* boolean autoDelete,
* Map<String, Object> arguments);
* queue:队列名
* durable:是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使
* 队列持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库
* exclusive:是否排外的,有两个作用,一:当连接关闭时connection.close()该队列是否会自动删除;二:该队列是否是私有的
* autoDelete:是否自动删除,当最后一个消费者断开连接之后队列是否自动被删除,可以通过RabbitMQ Management,
* 查看某个队列的消费者数量,当consumers = 0时队列就会自动删除
* arguments:队列中的消息什么时候会自动被删除?
*
*/
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
// 发送消息
String message = "Hello world ~~~";
/**
* channel.basicPublish 发布信息
* basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body);
* exchange:交换器名称
* routingKey:路由键,#匹配0个或多个单词,*匹配一个单词,在topic exchange做消息转发用
* props:消息路由头等的其他属性
* body:消息正文
*/
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println("[x] Send " + message + " ");
} catch (IOException e)
{
e.printStackTrace();
} catch (TimeoutException e)
{
e.printStackTrace();
}
}
}
Recv.java
package RabbitMQ.demo1;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;
/**
* 接受端
*/
public class Recv {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("120.79.XXX.XXX");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages.");
// 接受消息(有消息过来时会回调)
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
};
// 订阅消息
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
}
}
参考:
官网案例