什么是消息队列?
消息队列可以理解为一个盛放消息的“碗”,充当了一个容器的作用。举个例子,当我们手机关机时,接收不到微信的消息,但一旦打开手机。微信便会弹出消息通知,那么这些在我们手机关机时所发送的消息所存放的容器就叫做消息队列
由此,我们可以得到一个消息队列的大概消息模型模型
它具备三个部分
- 消息的“生产者”-Producer
- 存放消息的队列的容器,专业的术语叫做“消息主题”-Topic
- 消息的“消费者”-Consumer
可扩展的消息模型
有了上面的基础模型之后,消息队列便可以扩展为两个生产者-Producer、两组消费者-Consumer和两个消息主题-Topic
MessageQueue是什么?
为了消息写入能力的水平扩展,消息队列服务器对 Topic进行了分区,这种操作被称为队列(MessageQueue),Topic和MessageQueue共同组成了代理服务器——broker
ConsumerGroup是什么?
为了消费能力的水平扩展,ConsumerGroup的概念应运而生。
- 相同的ConsumerGroup下的消费者主要有两种负载均衡模式,即广播模式,和集群模式(图中是最常用的集群模式)
- 在集群模式下,同一个 ConsumerGroup 中的 Consumer 实例是负载均衡消费,如图中 ConsumerGroupA 订阅 TopicA,TopicA 对应 3个队列,则 GroupA 中的 Consumer1 消费的是 MessageQueue 0和 MessageQueue 1的消息,Consumer2是消费的是MessageQueue2的消息
- 在广播模式下,同一个 ConsumerGroup 中的每个 Consumer 实例都处理全部的队列。需要注意的是,广播模式下因为每个 Consumer 实例都需要处理全部的消息,因此这种模式仅推荐在通知推送、配置同步类小流量场景使用。
RockerMQ的部署模型
生产者 Producer
顾名思义,担任消息的发布角色;Producer通过 MQ 的负载均衡模块选择相应的 Broker 集群队列进行消息投递
消费者 Consumer
消息消费的角色
- 支持以推(push),拉(pull)两种模式对消息进行消费;通俗一点来说,就好像去商店买东西,push代表的就是自己主动询问老板有没有奥利奥饼干,而pull代表的就是商店老板主动向你推销奥利奥饼干。
- 提供实时消息订阅机制,可以满足大多数用户的需求。
名字服务器 NameServer
主要包含两个功能:
- Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活
- 路由信息管理,每个NameServer将保存关于 Broker 集群的整个路由信息和用于客户端查询的队列信息。Producer和Consumer通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费
名字服务器 NameServer通常会有多个实例部署,各实例间相互不进行信息通讯,Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,客户端仍然可以向其它NameServer获取路由信息。
代理服务器 Broker
主要的功能有:
- 消息的存储、投递、查询
- 服务的高可用保证
因为名字服务器 NameServer各个节点之间没有任何信息的同步,而Broker需要向其注册,所以部署相对复杂。
小结
- 每个 Broker 与 NameServer 集群中的所有节点建立长连接,定时注册 Topic 信息到所有 NameServer。
- Producer 与 NameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取Topic路由信息,并向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。Producer 完全无状态。
- Consumer 与 NameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Master、Slave 建立长连接,且定时向 Master、Slave发送心跳。Consumer 既可以从 Master 订阅消息,也可以从Slave订阅消息。
- 对于这些角色,我们来用一个可能不是很恰当的比喻
- 生产者——送货员(负责生产货物)
- 名字服务器——仓库大门的保安(负责指路)
- 代理服务器——仓库(负责存储、派发货物)
- 消费者——拉货员(负责将指定货物拉走)
RocketMQ的集群工作流程
启动NameServer
启动NameServer。NameServer启动后监听端口,等待Broker、Producer、Consumer连接,相当于一个路由控制中心。
启动 Broker
启动 Broker。与所有 NameServer 保持长连接,定时发送心跳包。心跳包中包含当前 Broker 信息以及存储所有 Topic 信息。注册成功后,NameServer 集群中就有 Topic跟Broker 的映射关系。
创建 Topic
创建 Topic 时需要指定该 Topic 要存储在哪些 Broker 上,也可以在发送消息时自动创建Topic
生产者发送消息
生产者发送消息。启动时先跟 NameServer 集群中的其中一台建立长连接,并从 NameServer 中获取当前发送的 Topic存在于哪些 Broker 上,轮询从队列列表中选择一个队列,然后与队列所在的 Broker建立长连接从而向 Broker发消息