聊聊 RocketMQ 名字服务
NameServer 是专为 RocketMQ 设计的轻量级名字服务,它的源码非常精简,八个类 ,少于1000行代码。
这篇文章, 笔者会从基础概念、Broker发送心跳包、NameServer 维护路由、Zookeeper vs NameServer 四个模块揭秘名字服务的设计精髓。
1 基础概念
NameServer 是一个非常简单的 Topic 路由注册中心,其角色类似 Dubbo 中的 zookeeper ,支持 Broker 的动态注册与发现。
RocketMQ 集群工作流程:
1、NameServer 启动服务,监听 TCP 端口 , 集群多节点之间无任何信息交互,然后等待 Broker、Producer 、Consumer 连上来;
2、Broker 启动后,每隔 30 秒向所有的 NameServer 发送心跳命令 ;
3、NameServer 接收到请求之后,保存路由信息在本地内存里 ,将响应结果返给 Broker 服务;
4、Producer 启动之后,会随机的选择一个 NameServer ,并从 NameServer 中获取当前发送的 Topic 存在哪些 Broker 上,轮询从队列列表中选择一个队列,然后与队列所在的 Broker 建立长连接从而向 Broker 发消息;
5、Consumer 跟 Producer 类似,跟其中一台 NameServer 建立长连接,获取当前订阅 Topic 存在哪些 Broker 上,然后直接跟 Broker 建立连接通道,开始消费消息。
2 Broker发送心跳包
我们贴一段 Broker 发送心跳命令的源码:
1、Broker 会每隔 30 秒向所有的 NameServer 发送心跳命令 ;
使用 CountDownLatch 实现多线程同步,可以获取发往所有的 NameServer 的心跳命令的响应结果
2、心跳命令包含两个部分:请求头和请求体
3 NameServer 维护路由
NameServer 在接收到 Broker 发送的心跳请求之后,通过默认的处理器来处理请求,保存路由信息成功后,注册成功状态返回给 Broker 服务。
源码中,我们可以看到路由信息保存在 HashMap 中 。
1、topicQueueTable:Topic 消息队列路由信息,包括 topic 所在的 broker 名称,读队列数量,写队列数量,同步标记等信息,rocketmq 根据 topicQueueTable 的信息进行负载均衡消息发送。
2、brokerAddrTable:Broker 节点信息,包括 brokername,所在集群名称,还有主备节点信息。
3、clusterAddrTable:Broker 集群信息,存储了集群中所有的 Brokername。
4、brokerLiveTable:Broker 状态信息,NameServer 每次收到 Broker 的心跳包就会更新该信息。
当 Broker 向 NameServer 发送心跳包(路由信息),NameServer 需要对 HashMap 进行数据更新,但我们都知道 HashMap 并不是线程安全的,高并发场景下,容易出现 CPU 100% 问题,所以更新 HashMap 时需要加锁,RocketMQ 使用了 JDK 的读写锁 ReentrantReadWriteLock 。
下面我们看下路由信息如何更新和读取:
1、写操作:更新路由信息,操作写锁
2、读操作:查询主题信息,操作读锁
我们可以将 NameServer 实现注册中心的方式总结为: RPC 服务 + HashMap 存储容器 + 读写锁 + 定时任务 。
1、NameServer 监听固定的端口,提供 RPC 服务
2、HashMap 作为存储容器
3、读写锁控制锁的颗粒度
4、定时任务
- 每个 Broker 每隔 30 秒注册主题的路由信息到所有 NameServer
- NameServer 定时任务每隔10 秒清除已宕机的 Broker , 判断宕机的标准是:当前时间减去 Broker 最后一次心跳时间大于2分钟
4 Zookeeper vs NameServer
那为什么 RocketMQ 不用 Zookeeper 做为注册中心呢 ?
我们先温习下 CAP 理论。
CAP 理论是分布式架构中重要理论。
1、一致性( Consistency ) :所有节点在同一时间具有相同的数据 ;
2、可用性( Availability ) :保证每个请求不管成功或者失败都有响应 (某个系统的某个节点挂了,但是并不影响系统的接受或者发出请求) ;
3、分隔容忍( Partition tolerance ) :系统中任意信息的丢失或失败不会影响系统的继续运作。 (在整个系统中某个部分,挂掉了,或者宕机了,并不影响整个系统的运作或者说使用) 。
Zookeeper 是一个典型的 CP 注册中心 ,通过使 ZAB 协议来保证节点之间数据的强一致性。
笔者曾经遇到过一起神州专车服务宕机事故,zookeeper 集群不堪重负,一直在选主 。 架构负责人修改了 zookeeper 的 jvm 参数,重启集群后 , 才临时解决了问题。
因为 MetaQ 集群和服务治理共用一组 zookeeper 集群 。
- MetaQ 消费者负载均衡时,会频繁的争抢锁 ,同时也会频繁的提交 offset ;
- 专车的注册服务也越来越多,注册信息通过Hession 序列化存储在 zookeeper 的节点。
为了减少 zookeeper 集群的性能压力,架构团队将 MetaQ 使用的 zookeeper 集群独立出来。
这次事故让我认识到: Zookeeper 作为 CP 注册中心,大规模使用场景下,它就变得很脆弱,我们要非常小心的使用。
淘宝中间件博客出了一篇文章 : 阿里巴巴为什么不用 ZooKeeper 做服务发现 ?
文章有两个观点,笔者认为非常有借鉴意义。
1、当数据中心服务规模超过一定数量 ( 服务规模=F{服务 pub 数,服务 sub 数} ),作为注册中心的 ZooKeeper 很快就会像下图的驴子一样不堪重负。
2、可以使用 ZooKeeper,但是大数据请向左,而交易则向右,分布式协调向左,服务发现向右。
相比 ZooKeeper ,NameServer 是一个典型的 AP 注册中心,它有如下优点:
1、代码不到 1000 行,实现简单,易于维护 ;
2、性能极好,除了网络消耗,基本都是本地内存操作 ;
3、服务都是无状态,且节点之间并不交互,运维简单;
RocketMQ 的设计者之所以选择自研名字服务,遵循着架构设计的准则,笔者总结为:简单、高效、适当妥协。
没有完美的技术,只有合适的技术,与诸君共勉。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
高效构建 vivo 企业级网络流量分析系统
作者:vivo 互联网服务器团队- Ming Yujia 随着网络规模的快速发展,网络状况的良好与否已经直接关系到了企业的日常收益,故障中的每一秒都会导致大量的用户流失与经济亏损。因此,如何快速发现网络问题与定位异常流量已经成为大型企业内必须优先解决的问题,诸多网络流量分析技术也同时应运而生。 一、概述 随着网络规模的快速发展,网络状况的良好与否已经直接关系到了企业的日常收益,故障中的每一秒都会导致大量的用户流失与经济亏损。每一家企业都在不断完善自己的网络监控手段,但在监控体系建设过程中,却又不可避免的面临以下难点: 网络流量数据庞大:由于网络流量的规模和复杂性都非常高,很难对大量的数据进行有效的监控和分析。 流量数据采集分析建设成本高昂:为获取准确的流量数据,需要使用高效的数据采集技术和大容量的存储设备,以及大量的开发资源,这使得监控成本直线上升 监控手段单一、缺乏扩展性:传统的监控手段一般只能监控固定的几个数据点,难以针对不同的网络环境进行定制化和扩展。 难以快速定位和解决问题:由于网络流量数据量大、变化频繁,往往需要花费大量的时间和精力才能找出问题根源。 因此,如何利用尽可能低的...
- 下一篇
图解算法,原理逐步揭开「GitHub 热点速览」
想必每个面过大厂的小伙伴都被考过算法,那么有没有更快了解算法的方式呢?这是一个老项目,hello-algo 用图解的方式让你了解运行原理。此外,SQL 闯关自学项目也是一个让你能好好掌握 SQL 技术的仓库。说回到面试,这个一周获得近 10k star 的 devops-exercises 定能让你好好刷一场面经。 最后,一定不能错过你的代码工,提一个带有你需求的 issue 就能搞定代码的 sweep。 以下内容摘录自微博@HelloGitHub 的 GitHub Trending 及 Hacker News 热帖(简称 HN 热帖),选项标准:新发布 | 实用 | 有趣,根据项目 release 时间分类,发布时间不超过 14 day 的项目会标注 New,无该标志则说明项目 release 超过半月。由于本文篇幅有限,还有部分项目未能在本文展示,望周知 🌝 本文目录 1. 本周特推 1.1 闯关式 SQL 自学:sql-mother 1.2 初级代码工:sweep 2. GitHub Trending 周榜 2.1 图片编辑器:Graphite 2.2 程序构建:dioxus ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题