聊聊 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 的设计者之所以选择自研名字服务,遵循着架构设计的准则,笔者总结为:简单、高效、适当妥协。
聊聊 RocketMQ 名字服务的更多相关文章
- Docker关联使用的一些工具:Clip名字服务(转载)
Clip名字服务 Clip(http://blog.puppeter.com/read.php?7)是一个名字服务C/S架构,它将传统的IP管理维度替换为名字服务即有意义可记忆的String.Clip ...
- nsswitch.conf - 系统数据库及名字服务开关配置文件
DESCRIPTION C 程序库里很多函数都需要配置以便能在本地环境正常工作, 习惯上是使用文件(例如`/etc/passwd') 来完成这一任务. 但别的名字服务, 如网络信息服务NIS, 还有域 ...
- nmbd - 向客户端提供构造在IP之上的NetBIOS名字服务的NetBIOS名字服务器
总览 SYNOPSIS nmbd [-D] [-F] [-S] [-a] [-i] [-o] [-h] [-V][-d <debug level>] [-H <lmhosts fil ...
- centos6 名字服务dnsmasq配置
1 主机名配置 主机hd1配置(后面配置为名字服务器) [grid_hd@hd1 Desktop]$ cat /etc/sysconfig/network NETWORKING=yes HOSTNAM ...
- 【Day02】Spring Cloud组件的使用--Nacos配置中心、sentinel流量控制、服务网关Gateway、RocketMQ、服务调用链路(Sleuth、zipkin)
今日内容 一.配置中心 1.遗留问题 yml配置,每一次都需要重启项目 需要不重启项目拿到更新的结果 引出:配置中心 选择:Spring Cloud Config组件 / Alibaba的Nacos( ...
- 聊聊SOA面向服务架构
什么是SOA SOA(Service-Oriented Architecture),即面向服务的架构.SOA是一种粗粒度.松耦合服务架构,服务之间通过简单.精确定义接口进行通讯,不涉及底层编程接口和通 ...
- 聊聊rocketmq的ConsumeMode.CONCURRENTLY
序 本文主要研究一下rocketmq的ConsumeMode.CONCURRENTLY ConsumeMode.CONCURRENTLY rocketmq-spring-boot-2.0.4-sour ...
- 聊聊rocketmq的sendBatchMessage
序 本文主要研究一下rocketmq的sendBatchMessage SendMessageRequestHeader rocketmq-all-4.6.0-source-release/commo ...
- zookeeper名字服务
10.12.67.31 #!/bin/shmkdir -p /data/zk-install/cd /data/zk-install/wget -q -O ons_agent-1.0.5.tar.gz ...
- Spring Cloud Alibaba | Sentinel: 服务限流基础篇
目录 Spring Cloud Alibaba | Sentinel: 服务限流基础篇 1. 简介 2. 定义资源 2.1 主流框架的默认适配 2.2 抛出异常的方式定义资源 2.3 返回布尔值方式定 ...
随机推荐
- SqlParameter的作用与用法
有时候为图方便,会直接用sqlhelper文件进行相关操作,会出现如下的类: public static object ExecuteScalar(string sqlStr, params SqlP ...
- 关于python中的OSError报错问题
Traceback (most recent call last): File "main.py", line 1, in <module> from trai ...
- JavaScript 如何判断一个对象中是否有某个属性?
今天讲讲,JavaScript 如何判断一个对象中是否有某个属性? 我总结了5个方法: 方法1: if(Obj[a]) {} 缺点:对于参数值为 undefined 和 0 的无效. 方法2: if( ...
- 2021-02-13:字符串str最少添加多少个字符变成回文串?
福哥答案2020-02-13: 假设字符串str是"abcde12344321",在str后添加"edcba"即可变成回文串.需要添加5个字符. 解法:包含最后 ...
- Anaconda网址
Anaconda: python全家桶,之前还有32位,现在需要64位. 官方网址:https://www.anaconda.com/ 国内源:https://mirrors.tuna.tsinghu ...
- 微软Build 2023两大主题:Copilots和插件
在本周大型微软人工智能 2023 开发者大会的开幕式上,人工智能站到了舞台中央--前台和后台以及介于两者之间的所有舞台. 贯穿会议的两个主要主题是Copilots - 涵盖广泛产品和服务的AI助手 - ...
- Springboot——参数校验
springboot参数校验注解 在controller层需要对前端传来的参数进行校验 校验简单数据类型 使用springboot自带的validation工具可以从后端对前端传来的数据进行校验 使用 ...
- 【python基础】if语句-语法格式
if语句-语法格式 简单理解if语句之后,我们的if语句语法格式有多种,选择使用哪种取决于要测试的条件数 1.if结构 最简单的if语句只有一个条件测试和一个代码块 其语法格式: 假设想要指导一个学员 ...
- JavaWeb入门必备JavaEE规范!
前言 对于学习 Java 的同学,大都是 Web 方向的.我们学习 JavaWeb 开发肯定是一个循序渐进的过程,学习前有一些前置知识要掌握,比如 JavaSE 相关知识,HTML.CSS.JavaS ...
- 【Python&GIS】根据像素坐标计算图片某点的地理/投影坐标
又是掉头发的一天,今天的任务是通过图片中心点的地理坐标以及图片中某点的像素坐标(即这个点位于图片中的x,y坐标)计算该点的地理/投影坐标.经过一整天的搜索,发现网上并没有这方面的教程. ...