目录
[1. MQ 是什么](#1. MQ 是什么)
[2. RabbitMQ 核心概念](#2. RabbitMQ 核心概念)
[2.1 Producer和Consumer](#2.1 Producer和Consumer)
[2.2 Connection和Channel](#2.2 Connection和Channel)
[2.3 Virtual host](#2.3 Virtual host)
[2.4 Queue](#2.4 Queue)
[2.5 Exchange](#2.5 Exchange)
[2.6 RabbitMQ工作流程](#2.6 RabbitMQ工作流程)
[3. AMQP](#3. AMQP)
[4. Web 界面操作](#4. Web 界面操作)
[4.1 用户相关操作](#4.1 用户相关操作)
[4.2 虚拟机相关操作](#4.2 虚拟机相关操作)
[5. RabbitMQ入门](#5. RabbitMQ入门)
[5.1 引入依赖](#5.1 引入依赖)
[5.2 编写生产者代码](#5.2 编写生产者代码)
[5.3 编写消费者代码](#5.3 编写消费者代码)
1. MQ 是什么
MQ(Message queue)本质上是个队列,先进先出,只不过队列里面的内容是消息,而消息非常简单,比如可以是文本字符串,JSON 等,也可以很复杂,例如内嵌对象,MQ 多用于分布式系统之间进行通信,系统之间的调用通常由两种方式
1)同步通信
直接调用对方服务,数据从一端发出后立刻就能达到另一端
2)异步通信
数据从一端发出后,先进入一个容器进行临时存储,当达到某种条件后,再由这个容器发送给另一端,容器的一个具体实现就是 MQ
MQ 的作用
1)异步解耦
在业务流程中,一些操作可能非常耗时,但并不需要即时返回结果,可能借助 MQ 把这些操作异步化,比如用户注册后发送短信或邮件通知,可以作为异步任务处理,而不必等待这些操作完成后才告知用户注册成功
2)流量削峰
在访问量剧增的情况下,应用仍然需要继续发挥作用,但这样的突发流量并不常见,使用 MQ 能够使关键组件支撑突发访问压力,不会因为突发流量而崩溃,例如秒杀活动,可以使用 MQ 来控制流量,将请求排队,然后系统根据自己的处理能力逐步处理这些请求
3)消息分发
当多个系统需要对同⼀数据做出响应时,可以使用 MQ 进行消息分发,比如支付成功后,⽀
付系统可以向 MQ 发送消息,其他系统订阅该消息,而无需轮询数据库
4)延时通知
在需要特定实践后发送通知的场景,可以使用 MQ 的延迟消息功能,例如下单后未支付,可以使用延迟队列在超时后自动取消订单
2. RabbitMQ 核心概念
在 rabbitmq 的界面上有 6 部分导航栏,下面介绍这 6 部分
RabbitMQ 是一个消息中间件,也是一个生产者消费者模型,它负责接收,存储并转发消息
2.1 Producer和Consumer
Producer:生产者,是 RabbitMQ Server 的客户端,向 RabbitMQ 发送消息
生产者创建消息,发布到 RabbitMQ 中,在实习应用中,消息通常是一个带有一定业务逻辑结构的数据,消息可以带有一定的标签,RabbitMQ 会根据标签进行路由,把消息发送给感兴趣的消费者
Consumer:消费者,也是 RabbitMQ Server 的客户端,从 RabbitMQ 中接收消息
消费者连接到 RabbitMQ 服务器,就可以消费消息,标签会被丢掉,消费者只会收到消息,并不知道消息的生产者是谁
Broker:就是 RabbitMQ Server,主要是接收和收发消息
对于 RabbitMQ 来说,一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ 服务器节点,或者 RabbitMQ 服务实例
2.2 Connection和Channel
Connection:连接,是客户端和 RabbitMQ 服务器之间的一个 TCP 连接,这个连接是建立消息传递基础,它负责传输客户端和服务器之间的所有数据和控制信息
Channel:通信,信道,Channel是在 Connection 之上的一个抽象层,在 RabbitMQ 中,一个 TCP 连接可以有多个 Channel,每个 Channel 都是独立的虚拟连接,消息的发送和接收都是基于 Channel 的
2.3 Virtual host
Virtual host:虚拟主机,它为消息队列提供了一种逻辑上的隔离机制,对于 RabbitMQ 而言,一个BrokerServer 上可以存在多个 Virtual host,当多个不同用户使用同一个 RabbitMQ Server 提供的服务时,可以虚拟划分出多个 vhost,每个用户在自己的 vhost 创建 exchange / queue 等
2.4 Queue
Queue:队列,是 RabbitMQ 的内部对象,用于存储消息
多个消费者,可以同时订阅同一个队列
2.5 Exchange
Exchange:交换机,message 到达 broker 的第一站,它负责接收生产者发送的消息,并根据特定的规则把这些消息路由到一个或者多个 Queue 中
2.6 RabbitMQ工作流程
1) Producer 生产了一条消息
2)Producer 连接到了 RabbitMQBroker,建立一个连接(Connection),开启了一个信道(Channel)
3)Producer 声明了一个交换机(Exchange),路由消息
4)Producer 声明了一个队列(Queue),存放信息
5)Producer 发送消息到 RabbitMQBroker
6)RabbitMQBroker 接收消息,并存入响应的队列中,如果没有找到对应的队列,则根据生产者的配置,选择丢弃或者退回给生产者
3. AMQP
AMQP 是一种高级消息队列协议,AMQP 定义了一套确定的消息交换功能,包括交换机,队列等,这些组件共同工作,使得生产者能够将消息发送到交换机,然后由队列接收并等待消费者接收
RabbitMQ 是遵从 AMQP 协议的,RabbitMQ 就是 AMQP 协议的 Erlang 的实现,AMQP 的模型结构和 RabbitMQ 的模型结构是一样的
4. Web 界面操作
4.1 用户相关操作
添加用户
1)点击 Admin --- Add user
2)设置账号密码及权限
3)观察是否添加成功
用户相关操作
1)在用户详情页面,进行更新或删除操作
设置对虚拟机的操作权限
更新 / 删除用户
退出当前用户
4.2 虚拟机相关操作
创建虚拟机
在 Admin 标签页下,点击右侧 Virtual Hosts --- Add a new virtual host,设置虚拟机的名称
5. RabbitMQ入门
5.1 引入依赖
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.20.0</version>
</dependency>
5.2 编写生产者代码
建立连接
1)IP
2)端口号
3)账号
4)密码
5)虚拟主机
java
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1. 建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("44.34.51.65");
connectionFactory.setPort(5672);//需要提前开放端口号
connectionFactory.setUsername("lk");//账号
connectionFactory.setPassword("lk");//密码
connectionFactory.setVirtualHost("study");//虚拟主机
Connection connection = connectionFactory.newConnection();
//2. 开启信道
Channel channel = connection.createChannel();
//3. 声明交换机 使用内置的交换机
//4. 声明队列
/**
* 参数说明:
* queue:队列名称
* durable:可持久化
* exclusive:是否独占
* autoDelete:是否自动删除
* arguments:参数
*
*/
channel.queueDeclare("hello",true,false,false,null);
//5. 发送消息
/**
* 参数说明:
* exchange:交换机名称
* routingKey:内置交换机,routingKey 和 队列名称保持一致
* props:属性配置
* body:消息
*/
String msg = "hello rabbitmq";
channel.basicPublish("","hello",null,msg.getBytes());
System.out.println("消息发送成功");
//6. 释放资源
channel.close();
connection.close();
}
}
执行生产者代码,观察结果
5.3 编写消费者代码
1)创建连接
2)创建 Channel
3)声明队列
4)消费消息
java
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1. 创建连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("44.34.51.65");
connectionFactory.setPort(5672);
connectionFactory.setUsername("lk");
connectionFactory.setPassword("lk");
connectionFactory.setVirtualHost("study");
Connection connection = connectionFactory.newConnection();
//2. 创建 Channel
Channel channel = connection.createChannel();
//3. 声明队列(可以省略)
channel.queueDeclare("hello",true,false,false,null);
//4. 消费消息
/**
* 参数说明:
* queue:队列名称
* autoAck:是否自动确认
* callback:接收到消息后,执行的逻辑
*/
DefaultConsumer consumer = new DefaultConsumer(channel) {
//从队列中收到消息就会执行的方法
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
String s = new String(body);
System.out.println("接收到的消息:" + s);
}
};
channel.basicConsume("hello",true,consumer);
//5. 释放资源
channel.close();
connection.close();
}
}
执行消费者代码,观察结果
其中,消费者代码和生产者前 3 步都是一样的
basicConsume:消费当前队列
Consumer
Consumer 用于定义消费消费者的行为,当需要从 RabbitMQ 中接收消息时,需要提供一个实现了Consumer 接口对象
DefaultConsumer 是 RabbitMQ 提供的一个默认消费者,实现了 Consumer 接口
核心方法:
handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body):从队列中接收到消息时,会自动调用该方法,在这个方法中,可以定义如何处理接收到的消息,打印消息等
参数说明:
consumerTag:消费者标签,通常时消费者在丁页队列时指定的
envelope:包含消息的封包信息,如队列名称,交换机等
properties:一些配置信息
body:消息的具体内容
实际上消费者相当于时一个监听程序,所以不需要关闭资源