开发者学堂课程【RocketMQ 知识精讲与项目实战(第三阶段):回顾 NameServer 架构设计】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/704/detail/12460
回顾 NameServer 架构设计
架构设计
消息中间件的设计思路一般是基于主题订阅发布的机制,消息生产者(Producer)发送某一个主题到消息服务器,消息服务器负责将消息持久化存储,消息消费者(Consumer)订阅该兴趣的主题,消息服务器根据订阅信息(路由信息)将消息推送到消费者〈Push模式)或者消费者主动向消息服务器拉去(Pull模式),从而实现消息生产者与消息消费者解耦。为了保证RocketMQ的broker的高可用,一般会搭建broker的集群。为了避免消息服务器的单点故障导致的整个系统瘫痪,通常会部署多台消息服务器共同承担消息的存储。那消息生产者如何知道消息要发送到哪台消息服务器呢?如果某一台消息服务器宕机了,那么消息生产者如何在不重启服务的情况下感知?
NameServer就是为了解决以上问题设计的。
Broker和NameServer之间有个心跳检测机制,心跳检测机制是Broker会定期上报自己的信息到NameServer,然后NameServer会维护所有Broker的信息,NameServer每隔三十秒会扫描它所维护的数据,检测是否有Broker未上传心跳信息。如果某一个broker超过120s还未上传心跳信息到NameServer,那NameServer会认为那个Broker宕机,之后会从所维护的列表中将这个宕机的Broker删除。这样可以保证producer从NameServer询问到的Broker是正常可用的。
当NameServer更新broker信息之后,比如将某个broker剔除,其不会主动向Producer或者Consumer推送最新的路由表信息,这样设计的目的是为追求简单高效。在下图流程中,NameServer的职责与zookeeper,但它的设计比zookeeper设计简单,使用zookeepr做broker的管理者,会导致与第三方耦合。RocketMQ使用NameServer是为了追求架构的简单。
Broker消息服务器在启动的时向所有NameServer注册,消息生产者(Producer)在发送消息时之前先从NameServer获取Broker服务器地址列表,然后根据负载均衡算法从列表中选择一台服务器进行发送。NameServer与每台Broker保持长连接,并间隔30S检测Broker是否存活,如果检测到Broker宕机,则从路由注册表中删除。但是路由变化不会马上通知消息生产者。这样设计的目的是为了降低NameServer实现的复杂度,在消息发送端提供容错机制保证消息发送的可用性。
NameServer本身的高可用是通过部署多台NameServer来实现,但彼此之间不通讯,也就是NameServer服务器之间在某一个时刻的数据并不完全相同,但这对消息发送并不会造成任何影响,这也是NameServer设计的一个亮点,总之,RocketMQ设计追求简单高效。