核心概念
界⾯上的导航栏共分6部分,这6部分分别是什么意思呢?
我们先看看RabbitMQ的⼯作流程:
RabbitMQ是⼀个消息中间件,也是⼀个⽣产者消费者模型.它负责接收,存储并转发消息.
Producer和Consumer
Producer: ⽣产者,是RabbitMQServer的客⼾端 ,向RabbitMQ发送消息
Consumer:消费者,也是RabbitMQServer的客⼾端 ,从RabbitMQ接收消息
Broker:其实就是RabbitMQServer,主要是接收和收发消息
- ⽣产者(Producer)创建消息,然后发布到RabbitMQ中.在实际应⽤中,消息通常是⼀个带有⼀定业务逻辑结构的数据,⽐如JSON字符串.消息可以带有⼀定的标签,RabbitMQ会根据标签进⾏路由,把消息发送给感兴趣的消费者(Consumer).
- 消费者连接到RabbitMQ服务器,就可以消费消息了,消费的过程中,标签会被丢掉.消费者只会收到消息,并不知道消息的⽣产者是谁,当然消费者也不需要知道.
- 对于RabbitMQ来说,⼀个RabbitMQBroker可以简单地看作⼀个RabbitMQ服务节点,或者RabbitMQ服务实例.⼤多数情况下也可以将⼀个RabbitMQBroker看作⼀台RabbitMQ服务器
Connection和Channel
Connection: 连接.是客⼾端和RabbitMQ服务器之间的⼀个TCP连接.这个连接是建⽴消息传递的基 础,它负责传输客⼾端和服务器之间的所有数据和控制信息.
Channel: 通道,信道.Channel是在Connection之上的⼀个抽象层.在RabbitMQ中,⼀个TCP连接可以 有多个Channel,每个Channel都是独⽴的虚拟连接.消息的发送和接收都是基于Channel的.
通道的主要作⽤是将消息的读写操作复⽤到同⼀个TCP连接上,这样可以减少建⽴和关闭连接的开销, 提⾼性能.
Virtual host
Virtual host: 虚拟主机.这是⼀个虚拟概念.它为消息队列提供了⼀种逻辑上的隔离机制.对于 RabbitMQ⽽⾔,⼀个BrokerServer上可以存在多个VirtualHost.
类似MySQL的"database",是⼀个逻辑上的集合.⼀个MySQL服务器可以有多个database
Queue
Queue: 队列,是RabbitMQ的内部对象,⽤于存储消息.
多个消费者,可以订阅同⼀个队列
一个消费者,也可以订阅多个队列
Exchange
Exchange: 交换机.message到达broker的第⼀站,它负责接收⽣产者发送的消息,并根据特定的规则 把这些消息路由到⼀个或多个Queue列中.
Exchange起到了消息路由的作⽤,它根据类型和规则来确定如何转发接收到的消息.
类似于发快递之后,物流公司怎么处理呢,根据地址来分派这个快递到不同的站点,然后再送到收件⼈⼿⾥.这个分配的⼯作,就是交换机来做的
RabbitMQ⼯作流程
流程:
- Producer⽣产了⼀条消息
- Producer连接到RabbitMQBroker,建⽴⼀个连接(Connection),开启⼀个信道(Channel)
- Producer声明⼀个交换机(Exchange),路由消息
- Producer声明⼀个队列(Queue),存放信息
- Producer发送消息⾄RabbitMQBroker
- RabbitMQBroker接收消息,并存⼊相应的队列(Queue)中,如果未找到相应的队列,则根据⽣产者 的配置,选择丢弃或者退回给⽣产者.
如果把RabbitMQ⽐作⼀个物流公司:
- Broker就类似整个物流公司的总部,它负责协调和管理所有的物流站点,确保包裹安全、⾼效地送达.
- Virtual Host可以看作是物流公司为不同的客⼾或业务部⻔划分的独⽴运营中⼼.每个运营中⼼都有⾃⼰的仓库(Queue),分拣规则(Exchange)和运输路线(Connection和Channel),这样可以确保不同客⼾的包裹处理不会相互⼲扰,同时提供定制化的服务
- Exchange就像是站点⾥的分拣中⼼.当包裹到达时,分拣中⼼会根据包裹上的标签来决定这个包裹 应该送往哪个⽬的地(队列).快递站点可能有不同类型的分拣中⼼,有的按照具体地址分拣,有的将包裹复制给多个收件⼈等.
- Queue就是快递站点⾥的⼀个个仓库,⽤来临时存放等待派送的包裹.每个仓库都有⼀个或多个快 递员(消费者)负责从仓库中取出包裹并派送给最终的收件⼈.
- Connection就像是快递员与快递站点之间的通信线路.快递员需要通过这个线路来接收派送任务 (消息).
- Channel就像是快递员在执⾏任务时使⽤的多个并⾏的通信线路.这样,快递员可以同时处理多个包裹,⽐如⼀边派送包裹,⼀边接收新的包裹
AMQP
AMQP(AdvancedMessageQueuingProtocol)是⼀种⾼级消息队列协议,AMQP定义了⼀套确定的 消息交换功能,包括交换器(Exchange),队列(Queue)等.这些组件共同⼯作,使得⽣产者能够将消息发 送到交换器.然后由队列接收并等待消费者接收.
AMQP还定义了⼀个⽹络协议,允许客⼾端应⽤通过该协议与消息代理和AMQP模型进⾏交互通信
RabbitMQ是遵从AMQP协议的,换句话说,RabbitMQ就是AMQP协议的Erlang的实现
AMQP的模型结构和RabbitMQ的模型结构是⼀样的.
web界⾯操作
用户相关操作
添加用户
添加后:
用户相关操作
点击查看⽤⼾详情 :
设置对虚拟机的操作权限:
更新/删除⽤⼾:
退出当前⽤⼾:
虚拟主机相关操作
创建虚拟主机
此操作会为当前登录用户设置虚拟主机
RabbitMQ快速⼊⻔
引入依赖
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.20.0</version>
</dependency>
编写生产者代码
- 建立连接(IP,端口号,账号,密码,虚拟主机)
- 开启信道
- 声明交换机
- 声明队列
- 发送信息
- 资源释放
java
public class ConsumerDemo {
public static void main(String[] args) throws IOException, TimeoutException {
//1.建立连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("119.91.154.99");
connectionFactory.setPort(5672);
connectionFactory.setUsername("xuexue");
connectionFactory.setPassword("xuexue");
connectionFactory.setVirtualHost("bit");
Connection connection = connectionFactory.newConnection();//获取连接
//2.开启信道
Channel channel = connection.createChannel();
//3. 声明交换机 使用内置的交换机
//4. 声明队列
/**
* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
* Map<String, Object> arguments)
* 参数说明:
* queue: 队列名称
* durable: 可持久化(消息到达队列之后,是否落盘)
* exclusive: 是否独占(只能一个消费者消费)
* autoDelete: 是否自动删除
* arguments: 参数
*/
channel.queueDeclare("hello",true,false,false,null );
//5. 发送消息
/**
* basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
* 参数说明:
* exchange: 交换机名称
* routingKey: 内置交换机, routingkey和队列名称保持一致
* props: 属性配置
* body: 消息
*/
for (int i = 0;i<10;i++){
String msg = "hello rabbitmq~"+i;
channel.basicPublish("","hello",null,msg.getBytes());
}
System.out.println("消息发送成功");
//6.资源释放
//channel.close();
//connection.close();
}
}
如果资源没有释放:
编写消费者代码
- 建立连接(IP,端口号,账号,密码,虚拟主机)
- 开启信道
- 声明队列
- 发送信息
- 资源释放
java
public class ProduceDemo {
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
//1. 创建连接
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("47.108.157.13");
connectionFactory.setPort(5672);
connectionFactory.setUsername("study");
connectionFactory.setPassword("study");
connectionFactory.setVirtualHost("bite");
Connection connection = connectionFactory.newConnection();
//2. 创建Channel
Channel channel = connection.createChannel();
//3. 声明队列(可以省略)
channel.queueDeclare("hello",true, false, false, null);
//4. 消费消息
/**
* basicConsume(String queue, boolean autoAck, Consumer callback)
* 参数说明:
* queue: 队列名称
* autoAck: 是否自动确认
* callback: 接收到消息后, 执行的逻辑
*/
DefaultConsumer consumer = new DefaultConsumer(channel){
//从队列中收到消息, 就会执行的方法
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("接收到消息:"+ new String(body));
}
};
channel.basicConsume("hello",true,consumer);
//等待程序执行完成
Thread.sleep(2000);
//5. 释放资源
channel.close();
connection.close();
}
}
在handleDelivery这个⽅法中,我们可以定义如何处理接收到的消息,例如打印消息内容,处理业务逻辑或者将消息 存储到数据库等
为什么消费者需要声明队列?
消费者启动时,需要指定订阅的队列,如果当时队列不存在,消费者会报错