RabbitMQ学习笔记(2)—-RabbitMQ基本知识

微信扫一扫,分享到朋友圈

RabbitMQ学习笔记(2)—-RabbitMQ基本知识

RabbitMQ是采用 Erlang 语言开发的 AMQP(Advanced Message Queuing Protocol,高级消息队例协议)的开源实现。 它最初起源于金融系统,用于在分布式系统中 存储转发 消息。

RabbitMQ的具体特点可以概括为以下几点:

  • 可靠性:RabbitMQ 使用一些机制来保证可靠性,如 持久化传输确认发布确认 等。
  • 灵活的路由:在消息进入队列之前,通过 Exchange 来路由消息。
  • 扩展性:多个MQ节点可以组成一个 集群 ,可以根据根据实际业务情况动态扩展集群。
  • 高可用性:队列可以在集群机器上设置 镜像 ,使得部分节点出现问题时队列仍然可用。
  • 多种协议:RabbitMQ 支持多种消息队列协议,除了AMQP外,还支持STOMP、MQTT等。
  • 多语言客户端:RabbitMQ 几乎支持所有常用语言,比如 Java、Python、C等;
  • 管理界面:RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 、节点等。(Web管理界面也是一种插件,还可以通过HTTP API进行管理)
  • 插件机制:RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

2. RabbitMQ相关概念

2.1 基本概念

RabbitMQ整体上是一个 生产者与消费者模型 ,主要负责接收、存储和转发消息。

RabbitMQ 模型架构 如下图:

上图中涉及的概念主要有:

(1)消息(Message)

消息 一般可以包含2个部分: 消息体消息属性消息体 (也成payload)一般是带有业务逻辑结构的数据,比如Json字符串; 消息属性 用于表述消息,比如消息对应的Exchange名称和RoutingKey。

(2)生产者(Producer)

生产者 就是发送消息的一方。

  • 个人理解本质上就是一个channel,channel执行了basicPublish的API。

(3)消费者(Consumer)

消费者 就是接收消息的一方。

  • 个人理解本质上就是一个channel,channel执行了basicConsume的API。

(4)队列(Queue)

队列 在RabbitMQ中用于 存储消息 。生产者所发送的消息最终被投递到队列中,消费者从队列获取消息并消费。

  • RabbitMQ中消息只存储在队列中,Exchange只做路由、不存储消息。
  • 所有队列都绑定到默认交换机exchange=””,并且绑定时使用的routingKey=queueName

(5)交换机(Exchange)

生产者将消息发送给 Exchange ,Exchange再将消息路由给队列。

  • 消息的路径是: 生产者 -> 交换机 -> 队列

(6)路由键(RoutingKey)

生产者在发送消息时,需要指定Exchange和 RoutingKey ,并且队列和Exchange之间的绑定关系也通过RoutingKey来标识。

(7)绑定(Binding)

绑定 可以理解为一个三元组<queueName, exchangeName, bindingKey>,表示将queue用bindingKey绑定到exchange,该exchange收到的消息时,会根据exchange类型和消息的routingKey将消息路由到符合的队列。

  • 也可以将交换机绑定到交换机。

(8)节点(Broker)

节点 是一个RabbitMQ服务器实例,一个集群中有多个节点,这些节点可以在多台机器上,也可以在同一台机器上(端口不同)。

(9)虚拟主机(Virtual Host)

虚拟主机 是共享相同身份认证和加密环境的独立服务器域。不同虚拟主机之间是 相互隔离 的,拥有独立的交换机、队列、绑定等。

  • 可以将 虚拟主机与节点之间的关系 理解为 数据库与mysql之间的关系 ,一台mysql服务上有不同的数据库。

(10)连接(Connection)

Connection 是客户端与服务器之间建立的一个网络连接。

(11)信道(Channel)

Channel 可以理解为一种轻量连接,多个channel共享一个Connection。

由于创建和销毁Connection的开销大,所以在Connection内部建立Channel。

互相隔离
双向
通过Channel完成

2.2 Exchange

2.2.1 交换机参数

以Java Channel接口API来说明创建交换机的主要参数。

Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete,
boolean internal, Map<String, Object> arguments) throws IOException;
复制代码
exchange
type
durable
autoDelete
internal
arguments

2.2.2 交换机类型

RabbitMQ常用交换机类型有 fanoutdirecttopic 四种。

2.2.2.1 广播模式(fanout)

当一个交换机是广播模式的话,所有绑定到该交换机上的队列(或交换机)都能收到路由的消息,不论bindingKey的取值。

  • 队列 而言,无论队列与交换机绑定时 bindingkey 取值是什么、也不论生产者发送消息时的 routingkey 是什么,该队列都可以收到广播交换机上所有消息。
  • 对于绑定到广播交换机上的 交换机 而言,同样如此。
    假设Exchange1是广播交换机,Exchange2是direct交换机,队列Queue1、Queue2绑定到Exchange2交换机。那么Exchange2可以收到Exchange1上所有消息,但是队列Queue1和Queue2只能收到routingKey(生产者设定)与bindingKey一致的消息。

2.2.2.2 direct模式

direct类型交换机会将消息路由到 bindingKey与routingKey完全一致 的队列上。(不再特别讨论交换机绑定到交换机的情况)

  • 一个队列可以使用不同的routingKey绑定到交换机多次,用于接收多种消息。比如对于消息时日志、日志分不同级别,queue1可以配置成接收debug、warning、info、error四种消息,queue2可以配置成只接收error消息。

2.2.2.3 topic模式

当routingKey中采用 点号 “.”分割时,bindingKey可以表现为类似 正则表达式 形式,此时队列可以接收到符合bindingKey规则的多个routingKey的消息,而不用像direct模式一样进行多次绑定。

  • 生产者发送消息时,使用的routingKey是完整的,且每个单词间用.分割。
  • bindingKey中可以使用特殊字符*和#,*用于匹配一个单词,#用于匹配零或多个单词。

如下图,对于routingKey为 quick.orange.rabbitlazy.orange.elephantquick.orange.foxlazy.brown.foxlazy.pink.rabbit ,Q1可以收到前3个routingKey的消息,Q2可以收到第1、2、4、5个routingKey的消息。

2.3 队列

同样以Java Channel接口API来说明创建队列的主要参数:

public Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive,
boolean autoDelete, Map<String, Object> arguments)
复制代码
  • queue :队列名。
  • durable :是否是持久化的。取值为true时,broker重启队列也存在。需要注意的是 队列持久化 不代表 消息持久化
    提一个项目中遇到的问题,项目中使用了RabbitMQ Cluster,且使用了持久化队列。在RabbitMQ Cluster中,队列只存在于一个broker上,当该broker不可访问(宕机、发生网络分区等原因),且没有镜像队列来保证高可用性,会使得队列不可用。由于业务上可以容忍短时间内一些数据丢失,这时候选择在重连时进行队列的删除、重新创建等操作,不过由于队列设置了持久化,会使得剩余broker同样存有队列元数据,导致无法执行删除动作,后考虑将队列durable属性设为false,这样队列所在节点宕机后,其它节点上也不存在队列,可以重新创建队列,保证一定程度可用性。
  • exclusive :是否是排他的。取值为true时,队列仅对首次声明它的Connection可见。包含以下含义:(1)队列存在时,后续执行声明队列的Connection无法访问队列;(2)占有队列的Connection内Channel都可以访问队列;(3)当占有队列的Connection断开时,队列将被自动删除。
  • autoDelete :是否是自动删除的。当队列被消费者连接过,之后 所有消费者连接 都断开时,队列将会被自动删除。包含以下含义:(1)当一个队列被创建了,还没有被消费时,队列是不会被删除的;(2)所有消费连接断开时,队列会被删除,即便现在还有生产者在发送消息,队列已经不存在了。
  • arguments

需要注意的是,每个队列都绑定了默认direct模式交换机,且bindingKey为队列名。需要直接往队列发送消息的话,可以设置 exchange=""routingKey=queueName

2.4 绑定

绑定可以分为 队列绑定到交换机交换机绑定到交换机

2.4.1 队列绑定到交换机

以Java Channel接口API来说明队列绑定到交换机的主要参数:

public Queue.BindOk queueBind(String queue, String exchange,
String routingKey, Map<String, Object> arguments)
复制代码
queue
exchange
routingKey

2.4.2 交换机绑定到交换机

以Java Channel接口API来说明交换机绑定到交换机的主要参数:

public Exchange.BindOk exchangeBind(String destination, String source,
String routingKey, Map<String, Object> arguments)
复制代码
  • destination :可以类比队列绑定的参数,用 消息传递的目的方 更好理解。
  • source :被绑定的交换机,用 消息传递的来源 更好理解。
  • routingKey :称为bindingKey更加合适。 被发送到 source交换机 的消息,如果消息的 routingkey 匹配 destination交换机bindingkey 或者说 source交换机 是广播模式,那么消息将被转发到 destination交换机

参考文献

官网:https://www.rabbitmq.com/
RabbitMQ实战指南
https://juejin.im/post/5a67f7836fb9a01cb74e8931
复制代码

微信扫一扫,分享到朋友圈

RabbitMQ学习笔记(2)—-RabbitMQ基本知识

搜狗联合新华社发布 3D AI 合成主播“新小微”

上一篇

到手价 299 元,小米小爱音箱 Art 正式发布:金属机身,立体声 2.0 , 茉莉情感音色

下一篇

你也可能喜欢

RabbitMQ学习笔记(2)—-RabbitMQ基本知识

长按储存图像,分享给朋友