说明
RabbitMQ 作为一个转发服务器,里面涉及了一些实体的东西,如下:
- 生产者 (Producter)
- 消息 (Message)
- 交换机 (Exchange)
- 队列 (Queue)
- 消费者 (Consumer)
在这些实体的东西的基础上,RabbitMQ 重点的是 交换机
,队列
交换机与队列
说完实体的东西之后,在 交换机
和 队列
之间有许多的规则(玩法),我们增加了如下内容:
队列名 (Queue_name)
交换机类型 (Exchange_type)
路由键 (Routing_key)
交换机类型、路由键的作用
路由键一般可以设置为某一类相同属性定义的集合
fanout (扇形类型) : 忽略了 Routing_key,类比广播模式,也算是类比发布者、订阅者模式
direct (直接类型) : 不忽略 Routing_key,为普通String,当 N 个 Consumer 绑定的 Routing_key 一致的时候,和
fanout
类型没区别topics (话题类型) : 不忽略 Routing_key,Routing_key 额外加多以个规则,如果需要为单词列表的时候,需要用
.
号进行分割,例如(c.a.i),除此之外,*
可以代表一个占位符,#
可以代表 0 或者多个占位符,例如(*.a.i),(c.#)headers (头部类型) : 略略略…日后补充
各类知识
交换机分发请求到队列
一个队列对应 N 个消费者
交换机分发请求的时候,用到了 Queue_name
和Routing_key
,默认情况下(同一个队列),交换机分发的策略是循环调度,例如,我现在有 2 个消费者,对应一个队列,分别叫C1
,C2
,第一次消息,队列会发送到C1
,第二次消息,队列会发送到C2
,以此循环调用。
这里会产生几个问题:
- 如果
C1
是一个耗时(sleep 1s)的操作,但是C2
是一个立刻执行完毕的队列。当前队列接受了交换机转发过来的 14 个消息,那么交换机会以循环调度的方式进行执行,消息的分配那么平均,C1 处理了 7 个消息的时候,C2 处理了 7 个消息,只不过 C2 进程会先完成任务,快将近一半的时间。
对策:RabbitMQ 中有一个qos
的概念,这个概念可以帮助类比网络模型里面的epoll
模式,当其中一个消费者空闲的时候,就把消息转发到该消费者上,在这种情况下的话,大大提高了整体消息消费的速率。但是也有弊端,就是如果所有的消费者都处于忙碌的状态的话,那么久可能需要考虑一下增加多一些消费者了。
- 如果消费者消费不及时,那么在队列中就会大量堆积消息,占用大量内存,导致服务器宕机或者 RabbitMQ 宕机,并且宕机的时候,大量消息随时面临了丢失的可能,这将会产生是否可怕的严重的后果
对策:RabbitMq 中有一个持久化
的概念,持久化支持队列持久化,消息持久化,为的就是防止宕机的时候,这些消息也跟之丢失。
- 消费者因为某些系统错误结束了,理论上,该消息会转发给另外一个正在运行的消费者去消费,如果这个时候,这个消费者也宕了,那么消息将会在队列中存储,直到下一个消费者连接的时候,会投递到消费者中。
对策:设定 ack 应答机制实现高可用的特性。