欢迎各位点赞👍 评论**✍收藏⭐**
1. Rabbit MQ 的传输模型
Rabbit MQ 的结构模型及工作流程如下

Rabbit MQ 简单来说就是一个生产者消费者模型,负责消息接受,储存,转发

1.1 生产者和消费者
- Producer:生产者,Rabbit MQ 的客户端,负责向Rabbit MQ 发送消息
- Consumer:消费者,Rabbit MQ 的客户端,负责从Rabbit MQ 接收消息
- Broker:就是 Rabbit MQ ,负责接受和发送消息

1.2 连接和信道
- Connection:连接,客户端和 Rabbit MQ 的一个 TCP 连接,负责传输客户端和服务器之间的各种信息
- Channel:信道,Channel 是建立在 Connecton 连接上的一个抽象层,一个 TCP 连接可以有多个Channel,连接上的消息接受和发送都依靠与 Channel 来实现的

1.3 虚拟机
- Virtual host :虚拟机,虚拟概念,相当于另一台主机,一个 Broker 上可以有多个虚拟机
1.4 队列
- Queue:队列,为Rabbit MQ 的底层内部对象,用于存储消息

多个消费者可以消费同一个队列

1.5 交换机
- Exchange:交换机,消息到达 Broker 的第一站,负责接受生产者的消息,并把消息路由到对应的 Queue 上,交换机是进行消息的路由,根据规则来决定路由到那个队列上

1.6 Rabbit MQ 的工作流程

- Producer 生产了一条消息,并与 Broker 建立了一个 Connection ,开启了一个 Channel
- Producer 声明一个 Exchange 路由消息,声明一个 Queue 存放消息
- 由 Exchange 把消息路由到对应的 Queue
- Consumer 与 Broker 建立一个 Connection ,开启一个 Channel
- Consumer 根据上方规则,取出消息,正常消费
2. AMQP 协议
AMQP 是一种高级消息队列协议,AMQP 定义一套确定的消息交换功能,包含交换机,队列等......,使生产者能够将消息发送到交换机,路由到队列,在由消费者从队列中取出消息
Rabbit MQ 就是遵守 AMQP 协议的,AMQP 的结构模型和Rabbit MQ 的结构模型是一样的

3. Rabbit MQ 代码实现
3.1 引入依赖
cpp
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.3</version>
</dependency>
3.2 生产者代码
3.2.1 创建连接
java
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置参数
factory.setHost("47.97.84.56");
factory.setPort(5672);
factory.setVirtualHost("test");
factory.setUsername("study");
factory.setPassword("123456");
//建立连接
Connection connection = factory.newConnection();
3.2.2 创建信道
java
//创建信道
Channel channel = connection.createChannel();
3.2.3 声明一个队列
java
/*
queueDeclare(String queue, boolean durable, boolean exclusive,
boolean autoDelete, Map<String, Object> arguments)
queue: 队列名称
durable: 是否持久化,true->为持久化,持久化的数据会存盘,服务器重启,数据不会丢失
exclusive: 是否独占, 只能有⼀个消费者监听队列,当Connection关闭时, 是否删除队列
autoDelete: 是否自动删除,当没有Consumer时,自动删除
*/
//如果没有 ok1 队列,则会自动创建,如果有,则不创建
channel.queueDeclare("ok1",true,false,false,null);
3.2.4 发送信息
当信息到达Rabbit MQ后,会先进入交换机中,如不特殊声明,则使用内置交换机,内置交换机的名称为(""),路由到对应的队列
java
/*
basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)
exchange: 交换机名称,非特定情况下,内置交换机名称为 ""
routingKey: 路由名称,routingKey = 队列名称
props: 配置信息
body: 消息数据
*/
String msg = "Hello Rabbit MQ!";
//使用内置交换机,默认名称为 "",routingKey 和队列名称一致,才能路由到对应的队列中
channel.basicPublish("","ok1",null,msg.getBytes(StandardCharsets.UTF_8));
System.out.println(msg + "消息发送成功!");
3.2.5 释放资源
用完Rabbit MQ 后及时关闭资源是一个好习惯
java
//关闭资源,必须先关闭信道,再关闭连接
channel.close();
connection.close();
3.3 消费者代码
前几步骤和上述一致,建立工厂,建立连接,声明信道和队列,消费消息时有差别
java
//消费信息
/*
basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoAck: 是否⾃动确认, 消费者收到消息之后,⾃动和MQ确认
callback: 回调对象
*/
System.out.println("消费者启动...");
DefaultConsumer consumer = new DefaultConsumer(channel) {
/*
回调⽅法, 当收到消息后, 会⾃动执⾏该⽅法
consumerTag: 标识
envelope: 获取⼀些信息, 交换机, 路由key
properties:配置信息
body:数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("接收到消息 " + new String(body));
}
};
channel.basicConsume("ok1",true,consumer);
//等待消费者消费
TimeUnit.SECONDS.sleep(5);
4. 生产者和消费者源码
4.1 生产者
java
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置参数
factory.setHost("47.97.84.56");
factory.setPort(5672);
factory.setVirtualHost("test");
factory.setUsername("study");
factory.setPassword("123456");
//建立连接
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
/*
queueDeclare(String queue, boolean durable, boolean exclusive,
boolean autoDelete, Map<String, Object> arguments)
queue: 队列名称
durable: 是否持久化,true->为持久化,持久化的数据会存盘,服务器重启,数据不会丢失
exclusive: 是否独占, 只能有⼀个消费者监听队列,当Connection关闭时, 是否删除队列
autoDelete: 是否自动删除,当没有Consumer时,自动删除
*/
//如果没有 ok1 队列,则会自动创建,如果有,则不创建
channel.queueDeclare("ok1",true,false,false,null);
/*
basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)
exchange: 交换机名称,非特定情况下,内置交换机名称为 ""
routingKey: 路由名称,routingKey = 队列名称
props: 配置信息
body: 消息数据
*/
System.out.println("生产者启动...");
String msg = "Hello Rabbit MQ!";
//使用内置交换机,默认名称为 "",routingKey 和队列名称一致,才能路由到对应的队列中
channel.basicPublish("","ok1",null,msg.getBytes(StandardCharsets.UTF_8));
System.out.println(msg + "消息发送成功!");
//关闭资源,必须先关闭信道,再关闭连接
channel.close();
connection.close();
}
}
4.2 消费者
java
public class Consumerr {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//设置参数
factory.setHost("47.97.84.56");
factory.setPort(5672);
factory.setVirtualHost("test");
factory.setUsername("study");
factory.setPassword("123456");
//建立连接
Connection connection = factory.newConnection();
//创建信道
Channel channel = connection.createChannel();
//创建队列
channel.queueDeclare("ok1",true,false,false,null);
//消费信息
/*
basicConsume(String queue, boolean autoAck, Consumer callback)
queue: 队列名称
autoAck: 是否⾃动确认, 消费者收到消息之后,⾃动和MQ确认
callback: 回调对象
*/
System.out.println("消费者启动...");
DefaultConsumer consumer = new DefaultConsumer(channel) {
/*
回调⽅法, 当收到消息后, 会⾃动执⾏该⽅法
consumerTag: 标识
envelope: 获取⼀些信息, 交换机, 路由key
properties:配置信息
body:数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("接收到消息 " + new String(body));
}
};
channel.basicConsume("ok1",true,consumer);
//等待消费者消费
TimeUnit.SECONDS.sleep(5);
//7. 释放资源 消费者相当于是⼀个监听程序, 不需要关闭资源
//顺序不可改变
//channel.close();
//connection.close();
}
}
5. 小结
以上就是对Rabbit MQ 的结构详解,传输机制介绍,具体还需宝子们去实践,如果觉得该博客对你有用的话,希望一键三连,点个关注不迷路,谢谢支持
