简介

消息中间件的设计思路一般都是基于主题的订阅发布机制,消息生产者发送某一主题的消息到消息服务器,消息服务器负责该消息的持久化存储,消息消费者订阅感兴趣的主题,消息服务器根据订阅信息(路由信息)将消息推送给消费者(推模式)或者消息消费者主动向消息服务器拉取消息(拉模式),从而实现消息生产者与消费者的解耦。为了避免因消息服务器的单点故障导致的整个系统瘫痪,通常会部署多台消息服务器共同承担消息的存储。那么消息生产者如何知道消息要发往哪台消息服务器?如果某一台消息服务器宕机了,生产者如何在不重启服务的情况下感知呢?消费者又是如何知道从哪台消息服务器上获取消息呢?

NameServer就是为了解决上述问题而设计的。NameServer是专门针对RocketMQ开发的轻量级协调者,多个NameServer节点可以组成一个NameServer集群,帮助RocketMQ集群达到高可用。

NameServer的主要功能是临时保存、管理Topic路由信息,各个NameServer节点是无状态的,即每两个NameServer节点之间不通信,互相不知道彼此的存在。

架构设计

NameServer中保存的数据被称为Topic路由信息Topic路由决定了Topic消息发送到哪些Broker,消费者从哪些Broker消费消息

Broker消息服务器在启动时向所有的NameServer注册,消息生产者在发送消息之前先从NameServer获取Broker服务器的地址列表,然后根据负载算法从列表中选择一台消息服务器发送消息。NameServer与每台Broker服务器保持长连接,并间隔10s检测Broker是否存活,如果检测到Broker宕机,则从路由注册表中将其移除,但是路由变化不会马上通知消息生产者。为什么要这么设计呢?这是为了降低NameServer实现的复杂性,因此需要在消息发送端提供容错机制来保证消息发送的高可用性。

上面说过,NameServer集群的节点是无状态的,各个节点之间互不通信。虽然NameServer服务器之间在某一时刻的数据并不完全相同,但对消息发送不会造成重大影响,无非就是短暂造成消息发送不均衡,这种设计主要是为了简化NameServer的复杂度,尽可能的提高性能,这也是NameServer设计最主要的思路。

消息客户端与NameServer、Broker的交互设计要点如下:

  • Brker每个30s向NameServer集群的每一台机器发送心跳包,包含自身创建的topic路由等信息。
  • 消息客户端每隔30s向NameServer更新对应topic的路由信息。
  • NameServer收到Broker发送的心跳包时会记录时间戳。
  • NameServer每隔10s会扫描一次brokerLiveTable(存放心跳包的时间戳信息),如果在120s内没有收到心跳包,则认为Broker失效,更新topic的路由信息,将失效的Broker信息移除。

NameServer和Zookeeper比较

  • 从角色角度,两者都是协调者
  • 从配置保存角度,NameServer将配置保存在内存;Zookeeper持久化到磁盘
  • 从是否支持选举角度,NameServer不支持选举;Zookeeper支持选举
  • 从数据一致性角度,NameServer是弱一致性,各个节点无状态,互不通信,依靠心跳保持数据一致;Zookeeper是强一致性
  • 从高可用角度,两者都是高可用设计
  • 从设计逻辑角度,NameServer仅仅是数据的CRUD;Zookeeper支持Raft选举,逻辑复杂难懂,排查问题较难

NameServer的路由原理

NameServer的主要作用是为消息生产者和消息消费者提供关于topic的路由信息,那么NameServer就需要存储路由的基础信息,并且能够管理Broker节点,包括路由注册、路由删除等功能。

NameServer路由元信息

那么路由信息都包含哪些数据呢?路由数据结构的实现代码都在RouteInfoManager类中,数据结构如下:

  • BROKER_CHANNEL_EXPIRED_TIME:broker存活的时间周日,默认为120s。
  • topicQueueTable:保存Topic和队列的信息,也是真正的路由信息,消息发送时根据路由表进行负载均衡。
  • brokerAddrTable:Broker基础信息,包括brokerName、所属集群名称、主备Broker地址。
  • clusterAddrTable:Broker集群信息,存储集群中所有的Broker的名称。
  • brokerLiveTable:Broker状态信息,NameServer每次收到心跳包时会替换该信息。
  • filterServerTable:Broker上的FilterServer列表,用于类模式消息过滤。类模式过滤机制在4.4及以后版本被废弃

注意:RockertMQ基于订阅发布机制,一个topic拥有多个消息队列,一个Broker默认为每一个主题创建4个读队列和4个写队列。多个Broker组成一个集群,BrokerName相同的多台Broker组成主从架构,brokerId=0代表主节点,brokerId>0表示从节点。BrokerLiveInfo中的lastUpdateTimestamp存储上次收到Broker心跳包的时间。

NameServer路由注册

Rocket路由注册是通过Broker与NameServer的心跳功能实现的。Broker启动时向集群中所有的NameServer发送心跳语句,之后每隔30s向集群中所有的NameServer发送心跳包,NameServer收到Broker心跳包时会先更新brokerLiveTable缓存中的BrokerLiveInfo的lastUpdateTimestamp,然后每隔10s扫描一次brokerLiveTable,如果连续120s没有收到心跳包,NameServer将移除Broker的路由信息,同时关闭Socket链接。

主要流程:
1.Broker发送心跳包
Rocket的网络传输基于Netty。Broker发送心跳包就是把一些必要的信息发送给NameServer,主要信息如下:

  • brokerAddr:broker地址。
  • brokerId:brokerId=0表示主节点,brokerId>0表示从节点。
  • brokerName:broker名称。
  • clusterName:broker所在集群的名称。
  • haServerAddr:主节点地址,初次请求时该值为空,从节点向NameServer注册后返回。
  • requestBody
    • topicConfigWrapper:主题配置,topicConfigWrapper内部封装的是TopicConfigManager中的topicConfigTable,内部存储的是Broker启动时默认的一些topic。Broker中topic默认存储在${Rocket_Home}/store/config/topics.json中。
    • filterServerList:消息过滤服务器列表。

2.NameServer处理心跳包

DefaultRequestProcessor是网络处理器解析请求类型,如果请求类型为RequestCode.REGISTER_BROKER,则请求最终转发到RouteInfoNanager#registerBroker。

  • 路由注册需要加写锁,防止并发修改RouteInfoManager中的路由表。首先判断Broker所属的集群是否存在,如果不存在,则创建集群,然后将broker名加入集群的Broker集合。
  • 维护BrokerData信息,首先从brokerAddrTable中根据broker名尝试获取Broker信息,如果不存在,则新建BrokerData并放入brokerAddrTable,registerFirst设置为true;如果存在直接替换原先的Broker信息,registerFirst设置为false,表示非第一次注册。
  • 如果Broker为主节点,并且Broker的topic配置信息发生变化或者是初次注册,则需要创建或者更新topic路由元数据,并填充topicQueueTable,其实就是为默认主题自动注册路由信息,其中包含MixAll.DEFAULT_TOPIC的路由信息。
  • 更新BrokerLiveInfo,存储状态正常的Broker信息表,BrokerLiveInfo是执行路由删除操作的重要依据。
  • 注册Broker的过滤器Server地址列表,一个Broker上会关联多个FilterServer消息过滤服务器。如果此Broker为从节点,则需要查找该Broker的主节点信息,并更新对应的masterAddr属性。

注意点:NameServer与Broker保持长连接,Broker的状态信息存储在brokerLiveTable中,NameServer每收到一个心跳包,将更新brokerLiveTable中关于Broker的状态信息以及路由表(topicQueueTable、brokerAddrTable、brokerLiveTable。filterServerTable)。更新上述路由表(HashTable)使用了锁粒度较小的读写锁,允许多个消息发送者并发读操作,保证消息发送时的高并发。同一时刻NameServer只处理一个Broker心跳包,多个心跳包请求串行执行,这也是读写锁经典的使用场景。

NameServer路由剔除

我们知道,Broker每隔30s向NameServer发送一个心跳包,心跳包中包含BrokerId、Broker地址、Broker名称、Broker所属集群名称。那么如果Broker宕机,NameServer无法收到心跳包,此时NameServer如何剔除失效的Broker呢?

NameServer会每隔10s扫描一次brokerLiveTable状态表,如果BrokerLive的lastUpdateTimestamp时间戳距当前时间超过120s,则认为Broker失效,移除该Broker,关闭与Broker的链接,同时更新topicQueueTable、brokerAddrTable、brokerLiveTable。filterServerTable。

RocketMQ有两个触发点来触发移除Broker信息:

  • NameServer定时扫描brokerLiveTable,检测上次心跳包与当前系统时间的时间戳差值是否大于120s,如果大于,则移除该Broker信息。
  • Broker在正常关闭的情况下,会执行unregisterBroker指令。

路由删除的具体步骤:

  • 申请写锁。根据brokerAddress从brokerLiveTable、filterServerTable中删除Broker相关的信息。
  • 维护brokerAddrTable。遍历HashMap<brokerName,BrokerData>brokerAddrTable,从BrokerData的HashMap<brokerId,broker address>brokerAddrs中,找到具体的Broker,从BrokerData中将其删除。如果移除后再BrokerData中不再包含其他Broker,则在brokerAddrTable中移除该brokerName对应的条目。
  • 根据BrokerName,从clusterAddeTable中找到Broker并将其从集群中移除。如果移除后,集群中不包含任何Broker,则将该集群从clusterAddrTable中移除。
  • 根据brokerName,遍历所有主题的队列,如果队列中包含当前Broker的队列,则移除,如果topic只包含待移除Broker的队列,从路由表中删除该topic。
  • 释放锁,完成路由删除。

NameServer路由发现

Rocket路由发现是非实时的,当topic路由出现变化后,NameServer不主动推送给客户端,而是由客户端定时拉取主题最新的路由

学习链接

学习更多有关RocketMQ的知识请参见RocketMQ之简介

Rocket之nameServer相关推荐

  1. Rocket之消息发送

    涉及角色 生产者组:一个逻辑概念,在使用生产者实例的时候需要指定一个组名.一个生产者组可以生产多个Topic的消息. 生产者实例:一个生产者组部署了多个进程,每个进程都可以称为一个生产者实例. Top ...

  2. Rocket mq的一些介绍

    概念 NameServer 相当于服务的注册中心,为整个MQ集群提供服务协调和治理; 可以部署多个,但是NameServer节点之间不会有通信,依靠Broker同时向所有的NameServer注册,上 ...

  3. Rocket MQ 详解

    开这个专栏主要之前实习的时候经常用到Rocket MQ,大厂使用的也比较多,主要讲解一些关键原理和概念. 介绍 定义:分布式消息中间件.MQ是消息队列的意思. 特点:低延迟.高并发.高可用.高可靠. ...

  4. RocketMq最强总结 带你rocket从入门到入土为安

    docker下安装单例RocketMq和集群 暂时之后再进行更新 rocket 各个角色分工 Producer:消息的发送者:举例:发信者 Consumer:消息接收者:举例:收信者 Broker:暂 ...

  5. Rocket MQ详解

    Rocket MQ 一,是啥,从哪来 RocketMQ是一个开源的分布式消息中间件,最初由阿里巴巴集团开发.它的设计目标是为了在高并发.高吞吐量的场景下,实现可靠的消息传输,并且具有良好的可伸缩性和可 ...

  6. 深入剖析RocketMQ源码-NameServer

    作者:vivo互联网服务器团队-Ye Wenhao 一.RocketMQ架构简介 1.1 逻辑部署图 (图片来自网络) 1.2 核心组件说明 通过上图可以看到,RocketMQ的核心组件主要包括4个, ...

  7. canal+mysql+rocket

    版本 canal.deployer-1.1.5 canal.admin-1.1.5 rocketmq-all-4.9.3-bin-release rocketmq-deshboard-master m ...

  8. Rocket 架构设计

    1 技术架构 RocketMQ架构上主要分为四部分,如上图所示: Producer:消息发布的角色,支持分布式集群方式部署.Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息 ...

  9. 基于 RT-Thread智能车控制算法开发-河南科技大学ROCKET

    学校:河南科技大学 队伍名称: ROCKET 参赛队员:王思杰.王磊 胡彧奇.程钟鑫 带队教师:王新勇.付江涛 §01 引言   在第 16届全国大学生智能汽车竞赛中,我们选择了双车接力组这一比赛项目 ...

最新文章

  1. IQueryable和IQueryProvider初尝
  2. struts2 18拦截器详解(五)
  3. 广西大学计算机类开设课程,操作系统教学大纲-广西大学计算机与电子信息学院.DOC...
  4. 微信小程序的基础 (一)
  5. 微信小程序之弹框modal
  6. 前端:JS/22/函数(函数的概念,函数的定义格式,函数定义格式的说明,函数的调用,函数的参数),全局变量和局部变量,拷贝传值和引用传址,匿名函数,二维数组,对象,自定义对象的创建
  7. yii和php的一些细节
  8. 祝贺吾博文中第一篇点击超过一万的文章出现
  9. DEVC使用问题集锦
  10. java1.8 ojdbc14.jar_ojdbc14_g.jar与ojdbc14.jar区别
  11. 以下选项中不是具体的python序列类型是_智慧树知到《大数据分析的python基础》章节测试答案...
  12. git 记住账号密码、忽略部分文件、合并分支、将远程分支拉取到本地
  13. siri中文语音助理_针对“语音助手”类产品,浅谈对话式交互设计
  14. 职业高中计算机英语必背单词,高中英语3500个必背单词.pdf
  15. 求大神解答!!!!在线死等!
  16. 什么是客户关系管理CRM?
  17. 符号_和平精英名字特殊符号怎么打?哪些特色符号可以用?
  18. PingCAP 与 DSG 达成战略合作,共同开启数据智能管理新篇章
  19. 少儿教育和游戏的火花在哪里?
  20. 制作电影影评网的html5代码,微信小程序之电影影评小程序制作代码

热门文章

  1. Layui提示说明弹框
  2. DNS云学堂 | 智能DNS让CDN乘风破浪
  3. Android系统安全机制
  4. 2019 年 DevOps 实践中最有价值的技能
  5. onlyoffice 回调传参数_OnlyOffice 部署与使用
  6. gorilla/mux 翻译
  7. mysql 安装插件 validate_password
  8. BUUCTF:[安洵杯 2019]吹着贝斯扫二维码
  9. 【MC 网易-我的世界-mod开发基础笔记】 --- 前期准备
  10. hello world漫游