聊聊RocketMQ名字服务

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: NameServer 是专为 RocketMQ 设计的**轻量级名字服务**,它的源码非常精简,八个类 ,少于1000行代码。

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 的设计者之所以选择自研名字服务,遵循着架构设计的准则,笔者总结为:简单高效适当妥协

没有完美的技术,只有合适的技术,与诸君共勉。

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
26天前
|
消息中间件 网络协议 物联网
MQTT常见问题之物联网设备端申请动态注册时MQTT服务不可用如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
1月前
|
NoSQL Java Redis
小白版的springboot中集成mqtt服务(超级无敌详细),实现不了掐我头!!!
小白版的springboot中集成mqtt服务(超级无敌详细),实现不了掐我头!!!
244 1
|
4月前
|
消息中间件 Linux 网络安全
Linux下源码安装RabbitMQ并设置服务开机启动
Linux下源码安装RabbitMQ并设置服务开机启动
79 0
|
2月前
|
传感器 监控 物联网
golang开源的可嵌入应用程序高性能的MQTT服务
golang开源的可嵌入应用程序高性能的MQTT服务
200 3
|
7月前
|
消息中间件 Java Linux
rocketmq linux注册服务开机启动配置
rocketmq linux注册服务开机启动配置
257 1
|
2月前
|
网络协议 Go 数据安全/隐私保护
golang开源的可嵌入应用程序高性能的MQTT服务
golang开源的可嵌入应用程序高性能的MQTT服务
252 2
|
11天前
|
网络协议 Java 物联网
阿里云服务器上搭建 MQTT服务
阿里云服务器上搭建 MQTT服务
|
8月前
|
消息中间件 Linux
centos7 yum快速安装rabbitmq服务
centos7 yum快速安装rabbitmq服务
137 0
|
4月前
|
消息中间件 开发工具 数据安全/隐私保护
RabbitMQ【部署 01】一篇学会RabbitMQ服务依赖的下载安装及简单使用(首次登录 User can only log in via localhost 问题处理)
RabbitMQ【部署 01】一篇学会RabbitMQ服务依赖的下载安装及简单使用(首次登录 User can only log in via localhost 问题处理)
78 0
|
7月前
|
消息中间件 网络协议 Ubuntu
在Ubuntu Linux系统上安装RabbitMQ服务并解决公网远程访问问题
在Ubuntu Linux系统上安装RabbitMQ服务并解决公网远程访问问题