RabbitMQ–基础–04–运转流程
1、在最初状态下,Producer(生产者)发送消息的流程
- Producer 连接到 Broker,建立一个Conection(TCP连接),开启一个Channel(信道)
- Producer 声明一个交换机,并设置相关属性,属性包括如下
- 交换机类型
- 是否持久化等
- Producer 声明一个队列,并设置相关属性,属性包括如下
- 是否持久化
- 是否排他
- 自动删除等
- Producer 通过绑定键(BindingKey)将交换机(Exchange)和队列(Queue)绑定起来
- Producer 发送消息至 Broker,其中信息包括
- 路由键
- 交换器等信息
- 相应的交换机 Exchange 根据接收到的路由键查找相匹配的队列
- 如果找到,则将从Producer 发送过来的消息存入相应的队列中去
- 如果没有找到,则根据Producer配置的属性
- 可以选择丢弃
- 可以选择回退给Producer
- 关闭信道 Channel,Connection
2、Consumer(消费者)接收消息的过程
- Consumer连接到 Broker, 建立一个Conection(TCP 连接),开启一个Channel(信道)
- Consumer向 Broker 请求消费相应队列中的消息,可能会设置相应的回调函数,以及做一些准备工作
- 等待 Broker 回应并投递相应队列中的消息,Consumer接收消息
- Consumer确认 ACK 接收到的消息
- RabbitMQ 从队列中删除相应已经被确认的消息
- 关闭信道、连接
3、consumer接收消息后,队列对ACK的处理情况
- 如果consumer接收消息后发送ack,rabbitmq会删除队列中这个消息,发送另一条消息给consumer。
- 如果cosumer接收了消息,但在发送ack之前断开连接,rabbitmq会认为这条消息没有发送成功,在consumer再次连接的时候,rabbitmq会再次发送这条消息。
- 如果consumer接收了消息,但是程序中如果忘记了ack/nack,rabbitmq不会重复推此消息到consumer,但是,在consumer再次连接的时候,rabbitmq会再次发送这条消息。
- rabbitmq2.0.0和之后的版本支持consumer reject某条(类)消息,可以通过设置requeue参数中的reject为true,那么rabbitmq将会把消息发送给下一个注册的consumer。
4、总结
- 根据上述过程,无论Producer还是Consumer,都需要和 RabbitMQ Broker 建立连接,这个连接就是一条 TCP连接(Connection)
- 一旦 TCP连接 建立起来,客户端紧接着可以创建一个 AMQP 信道(Channel),每个信道都会被指派一个唯一的 ID。
- 信道(Channel) 是建立在 Connection 之上的虚拟连接,RabbitMQ 处理每条 AMQP 指令都是通过信道 Channel 完成的。
4.1、我们完全可以直接使用 Connection 就能完成信道的工作,为什么还要引入信道 Channel 呢?
4.1.1、场景
一个应用程序中有很多个线程需要从 RabbitMQ 中消费消息,或者生产消息,那么,必然需要建立很多个 Connection,也就是许多个 TCP连接。然而,对于操作系统而言,建立和销毁 TCP连接 是非常昂贵的开销,如果遇到使用高峰,性能瓶颈也随之显现。
4.1.2、解决方案
- RabbitMQ 采用类似于 NIO 的做法,选择 TCP 连接复用,不仅可以减少性能开销,同时也便于管理。
- 每个线程把持一个信道,所以,信道复用了 Connection 的 TCP 连接。同时,RabbitMQ 可以确保每个线程的私密性,就像拥有独立的连接一样。