RocketMQ整体架构及NameServer源码分析

news2024/11/27 21:44:00

RocketMQ源码深入剖析

1 RocketMQ介绍

RocketMQ 是阿里巴巴集团基于高可用分布式集群技术,自主研发的云正式商用的专业消息中间件,既可为分布式应用系统提供异步解耦和削峰填谷的能力,同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性,是阿里巴巴双 11 使用的核心产品。

1.1 RocketMQ4.X版本更新概要

  • 在 RocketMQ 4.3.0 版本之后,正式发布事务消息,通过类似于两阶段的方式去解决上下游数据不一致问题。
  • 在 RocketMQ 4.4.0 版本中,RocketMQ 增加了消息轨迹的功能,使用户可以更好定位每一条消息的投放接收路径,帮助问题排查,另外还增加 ACL 权限控制,提高了 RocketMQ 的管控能力和安全性。
  • 在 4.5.0 版本中,RocketMQ 推出了多副本,也就是 Raft 模式。在 Raft 模式下,一组 Broker 如果 Master 挂了,那么 Broker 中其他 Slave 就会重新选出主。因此 Broker 组内就拥有了自动故障转移的能力,也解决了像高可用顺序消息这样的问题,进一步提高了 RocketMQ 的可用性。
  • 在 4.6.0 版本中,我们推出了轻量级 Pull Consumer,用户可以使用更加适合于流计算的 API,这一版本也开始支持全新的 Request-Reply 消息,使得 RocketMQ 具备了同步调用 RPC 的能力,RocketMQ 可以更好的打破网络隔离网络之间的调用,这个版本中 RocketMQ 也开始支持 IPV6,并且是首个支持 IPV6 的消息中间件。
  • 在 4.7.0 版本中,RocketMQ 重构了主备同步复制流程,通过线程异步化,将同步复制和刷盘的过程 Pipeline 化,同步双写性能有将近数倍提升。
  • 在 4.8.0 版本中,RocketMQ Raft 模式有了一个质的提升,包括通过异步化、批量复制等手段将性能提升了数倍,在稳定性上利用 OpenChaos 完成包括宕机、杀死进程,OOM、各种各样的网络分区和延迟的测试,修复了重要 Bug。在功能上,支持 Preferred Leader,从而 Broker 组内可以优先选主,也支持了批量消息等功能。
  • 在 4.9.0 版本,主要是提升了可观测性,包括支持 OpenTracing,事务消息和 Pull Consumer 支持 Trace 等功能。

1.2 为什么要学RocketMQ源码

  • 编写优雅、高效的代码经验

    RocketMQ作为阿里双十一交易核心链路产品,支撑千万级并发、万亿级数据洪峰。读源码可以积累编写高效、优雅代码的经验。

  • 提升微观的架构设计能力,重点在思维和理念

    Apache RocketMQ作为Apache顶级项目,它的架构设计是值得大家借鉴的。

  • 解决工作中、学习中的各种疑难杂症

    在使用RocketMQ过程中遇到消费卡死、卡顿等问题可以通过阅读源码的方式找到问题并给予解决。

  • 在BATJ一线互联网公司面试中展现优秀的自己

    大厂面试中,尤其是阿里系的公司,你有RocketMQ源码体系化知识,必定是一个很大的加分项。

1.3 RocketMQ源码中的技术亮点

  • 读写锁
  • 原子操作类
  • 文件存储设计
  • 零拷贝:MMAP
  • 线程池
  • ConcurrentHashMap
  • 写时复制容器
  • 负载均衡策略
  • 故障延迟机制
  • 堆外内存

2 RocketMQ核心组件

image.png

NameServer

命名服务,更新和路由发现 broker服务。NameServer的作用是为消息生产者、消息消费者提供关于主题 Topic 的路由信息,NameServer除了要存储路由的基础信息,还要能够管理 Broker节点,包括路由注册、路由删除等功能。

Producer/Consumer

java版本的MQ客户端实现,包括生产者和消费者。

Broker

它能接收producer和consumer的请求,并调用store层服务对消息进行处理。HA服务的基本单元,支持同步双写,异步双写等模式。

Store

存储层实现,同时包括了索引服务,高可用HA服务实现。

Netty Remoting Server/Netty Remoting Client

基于netty的底层通信实现,所有服务间的交互都基于此模块。也区分服务端和客户端

3 RocketMQ源码下载及安装

3.1 下载地址

官方下载地址:http://rocketmq.apache.org/dowloading/releases/

本课程使用的是4.8.0的版本

image.png

3.2 环境要求

  • Linux64位系统
  • JDK1.8(64位)
  • Maven 3.2.x

3.3 使用IntelliJ IDEA导入安装源码

下载且已经解压后的代码导入后执行Maven命令install:

mvn install -Dmaven.test.skip=true

image.png

3.4 配置与运行RocketMQ

3.4.1 启动NameServer

RocketMQ启动必须先启动NameServer,启动类是namesrv/目录下的NamesrvStartup类,不过在运行这个类之前必须要配置环境变量ROCKETMQ_HOME,变量值为RocketMQ的运行主目录。

image.png

RocketMQ的运行主目录一般使用新建的方式,同时在运行主目录中创建conf、logs、store三个文件夹,然后从源码目录中distribution目录下的中将broker.conf、logback_broker.xml、logback_namesrv.xml复制到conf目录中。

image.png

image.png

最后运行namesrv/目录下的NamesrvStartup类的main方法,NameServer启动成功!

image.png

3.4.2 启动Broker

在broker模块找到broker模块,同时找到启动类BrokerStartup.java

image.png

源码启动前需要修改配置文件broker.conf (修改RocketMQ的消息存储路径)

image.png

配置环境变量,同时启动时需要加入参数(指定启动的配置文件)

image.png

broker启动成功后的控制台如下:

image.png

3.5 控制台安装及部署

3.5.1 环境要求

运行前确保:已经有jdk1.8,Maven(打包需要安装Maven3.2.x)

3.5.2 下载

老版本地址下载:https://codeload.github.com/apache/rocketmq-externals/zip/master

新版本地址:https://github.com/apache/rocketmq-dashboard

解压后如图(以下使用的是老版本,新版本参考老版本即可)

image.png

3.5.3 配置

后端管理界面是一个Java工程,独立部署,同时也需要根据不同的环境进行相关的配置。

控制台端口及服务地址配置:

下载完成之后,进入‘\rocketmq-console\src\main\resources’文件夹,打开‘application.properties’进行配置。

image.png

进入‘\rocketmq-externals\rocketmq-console’文件夹,执行‘mvn clean package -Dmaven.test.skip=true’,编译生成运行jar包。

image.png

编译成功之后,cmd命令进入‘target’文件夹,执行‘java
-jar rocketmq-console-ng-2.0.0.jar’,启动‘rocketmq-console-ng-2.0.0.jar’。

image.png

浏览器中输入‘127.0.0.1:8089’,成功后即可进行管理端查看。

image.png

4 RocketMQ的核心三流程

image.png

整体模块如下:
rocketmq-namesrv: 注册中心,命名服务,更新和路由发现 broker服务。
NameServer 要作用是为消息生产者、消息消费者提供关于主题 Topic 的路由信息,NameServer除了要存储路由的基础信息,还要能够管理 Broker节点,包括路由注册、路由删除等功能
rocketmq-broker: mq的核心。
它能接收producer和consumer的请求,并调用store层服务对消息进行处理。HA服务的基本单元,支持同步双写,异步双写等模式。
rocketmq-store: 存储层实现,同时包括了索引服务,高可用HA服务实现。
rocketmq-remoting: 基于netty的底层通信实现,所有服务间的交互都基于此模块。
rocketmq-common: 一些模块间通用的功能类,比如一些配置文件、常量。
rocketmq-client: java版本的mq客户端实现
rocketmq-filter: 消息过滤服务,相当于在broker和consumer中间加入了一个filter代理。
rocketmq-srvutil: 解析命令行的工具类ServerUtil。
rocketmq-tools: mq集群管理工具,提供了消息查询等功能

RocketMQ的源码是非常的多,我们没有必要把RocketMQ所有的源码都读完,所以我们把核心、重点的源码进行解读,RocketMQ核心流程如下:

  • 启动流程
    RocketMQ服务端由两部分组成NameServer和Broker,NameServer是服务的注册中心,Broker会把自己的地址注册到NameServer,生产者和消费者启动的时候会先从NameServer获取Broker的地址,再去从Broker发送和接受消息。
  • 消息生产流程
    Producer将消息写入到RocketMQ集群中Broker中具体的Queue。
  • 消息消费流程
    Comsumer从RocketMQ集群中拉取对应的消息并进行消费确认。

5 NameServer源码分析

5.1 NameServer整体流程

NameServer是整个RocketMQ的“大脑”,它是RocketMQ的服务注册中心,所以RocketMQ需要先启动NameServer再启动Rocket中的Broker。

image.png

  • NameServer启动
    启动监听,等待Broker、Producer、Comsumer连接。Broker在启动时向所有NameServer注册,生产者在发送消息之前先从NameServer获取Broker服务器地址列表,然后根据负载均衡算法从列表中选择一台服务器进行消息发送。消费者在订阅某个主题的消息之前从NamerServer获取Broker服务器地址列表(有可能是集群),但是消费者选择从Broker中订阅消息,订阅规则由 Broker 配置决定。
  • 路由注册
    Broker启动后向所有NameServer发送路由及心跳信息。
  • 路由剔除
    移除心跳超时的Broker相关路由信息。NameServer与每台Broker服务保持长连接,并间隔10S检查Broker是否存活,如果检测到Broker宕机,则从路由注册表中将其移除。这样就可以实现RocketMQ的高可用。

5.2 NameServer启动流程

从源码的启动可知,NameServer单独启动。
入口类:NamesrvController
核心方法:NamesrvController 类中main()->main0-> createNamesrvController()->start() -> initialize()

流程图如下:

image.png

5.2.1 加载KV配置

核心解读NamesrvController类中createNamesrvController()

image.png

在源码中发现还有一个p的参数,直接在启动个参数中送入 -p 就可以打印这个NameServer的所有的参数信息(不过NameServer会自动终止),说明这个-p是一个测试参数。

image.png

image.png

正常启动时,也可以在启动日志中一定可以找到所有的参数:

image.png

image.png

5.2.2 构建NRS通讯接收路由、心跳信息

image.png

image.png

image.png

5.2.3 定时任务剔除超时Broker

核心控制器会启动定时任务: 每隔10s扫描一次Broker,移除不活跃的Broker。

Broker每隔30s向NameServer发送一个心跳包,心跳包包含BrokerId,Broker地址,Broker名称,Broker所属集群名称、Broker关联的FilterServer列表。但是如果Broker宕机,NameServer无法收到心跳包,此时NameServer如何来剔除这些失效的Broker呢?NameServer会每隔10s扫描brokerLiveTable状态表,如果BrokerLive的lastUpdateTimestamp的时间戳距当前时间超过120s,则认为Broker失效,移除该Broker,关闭与Broker连接,同时更新topicQueueTable、brokerAddrTable、brokerLiveTable、filterServerTable。

image.png

image.png

路由剔除机制中,Borker每隔30S向NameServer发送一次心跳,而NameServer是每隔10S扫描确定有没有不可用的主机(120S没心跳),那么问题就来了!这种设计是存在问题的,就是NameServer中认为可用的Broker,实际上已经宕机了,那么,某一时间段,从NameServer中读到的路由中包含了不可用的主机,会导致消息的生产/消费异常,不过不用担心,在生产和消费端有故障规避策略及重试机制可以解决以上问题(原理后续源码解读)。这个设计符合RocketMQ的设计理念:整体设计追求简单与性能,同时这样设计NameServer是可以做到无状态化的,可以随意的部署多台,其代码也非常简单,非常轻量。

image.png

RocketMQ有两个触发点来删除路由信息:

  • NameServer定期扫描brokerLiveTable检测上次心跳包与当前系统的时间差,如果时间超过120s,则需要移除broker。

  • Broker在正常关闭的情况下,会执行unregisterBroker指令这两种方式路由删除的方法都是一样的,都是从相关路由表中删除与该broker相关的信息。

    在消费者启动之后,第一步都要从NameServer中获取Topic相关信息

5.3 NameServer设计亮点

5.3.1 读写锁

RouteInfoManager类中有一个读写锁的设计

image.png

消息发送时客户端会从NameServer获取路由信息,同时Broker会定时更新NameServer的路由信息,所以路由表会有非常频繁的以下操作:

1、 生产者发送消息时需要频繁的获取。对表进行读。

RouteInfoManager类

image.png

2、 Broker定时(30s)会更新一个路由表。对表进行写。

RouteInfoManager类

image.png

因为Broker每隔30s向NameServer发送一个心跳包,这个操作每次都会更新Broker的状态,但同时生产者发送消息时也需要Broker的状态,要进行频繁的读取操作。所以这个地方就有一个矛盾,Broker的状态会被经常性的更新,同时也会被更加频繁的读取。这里如何提高并发,尤其是生产者进行消息发送时的并发,所以这里使用了读写锁机制(针对读多写少的场景)。

synchronized和ReentrantLock基本都是排他锁,排他锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞。读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。

5.3.2 存储基于内存

NameServer存储以下信息:

topicQueueTable:Topic消息队列路由信息,消息发送时根据路由表进行负载均衡

brokerAddrTable:Broker基础信息,包括brokerName、所属集群名称、主备Broker地址

clusterAddrTable:Broker集群信息,存储集群中所有Broker名称

brokerLiveTable:Broker状态信息,NameServer每次收到心跳包是会替换该信息

filterServerTable:Broker上的FilterServer列表,用于类模式消息过滤。

image.png

NameServer的实现基于内存,NameServer并不会持久化路由信息,持久化的重任是交给Broker来完成。这样设计可以提高NameServer的处理能力。

5.3.3 NameServer无状态化

image.png

  • NameServer集群中它们相互之间是不通讯
  • 主从架构中,Broker都会向所有NameServer注册路由、心跳信息
  • 生产者/消费者同一时间,与NameServer集群中其中一台建立长连接

项目实战部署分析:

假设一个RocketMQ集群部署在两个机房,每个机房都有一些NameServer、Broker和客户端节点,当两个机房的链路中断时,所有的NameServer都可以提供服务,客户端只能在本机房的NameServer中找到本机房的Broker。

RocetMQ集群中,NameSever之间是不需要互相通信的,所以网络分区对NameSever本身的可用性是没有影响的,如果NameSever检测到与Broker的连接中断了,NameServer会认为这个Broker不再能提供服务,NameServer会立即把这个Broker从路由信息中移除掉,避免客户端连接到一个不可用的Broker上去。
网络分区后,NameSever 收不到对端机房那些Broker的心跳,这时候,每个Namesever上都只有本机房的Broker信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1008670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无涯教程-JavaScript - ISLOGICAL函数

描述 如果指定的值或表达式的计算输出为逻辑值,即True或False,则ISLOGICAL函数将返回逻辑值TRUE。否则返回FALSE。 语法 ISLOGICAL (value)争论 Argument描述Required/OptionalvalueValue or expression.Required Notes 您可以在执行计算之前使用此功能测试单元格的内容。…

《机器学习核心算法》分类算法 - 朴素贝叶斯 MultinomialNB

「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:小白零基础《Python入门到精通》 朴素贝叶斯 1、朴素贝叶斯API2、朴素贝叶斯算法实际应用2.1、获取数据集2.2、划分…

【译】怎样修改 HashMap 的 Key?

原文地址:https://www.baeldung.com/java-hashmap-modify-key 1. 概述 在 Java 中,HashMap 是一个广泛使用的数据结构,它以键值对的形式存储元素,提供快速的数据访问和检索。有时,在使用 HashMap 时,我们…

【算法题】1222. 可以攻击国王的皇后

题目: 在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。 给定一个由整数坐标组成的数组 queens ,表示黑皇后的位置;以及一对坐标 king ,表示白国王的位置,返回所有可以攻击国王的皇后的坐标(…

重启人生,重新出发

Hello, World! 我是EarlGrey,这是时隔两年多后在公众号第一次发文。也许有些老朋友已经忘记我了,也有少数朋友是最近才开始关注的,所以谈正题之前,我先花点时间介绍一下自己。 我是谁 我是英语专业出身,从北外高翻毕业…

使用 SimPowerSystems 的混合技术风电场的无功功率管理(Simulink)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

什么是 JxBrowser

什么是 JxBrowser 文章目录 什么是 JxBrowser如何使用 JxBrowser容易集成支持的平台Java丰富的文档如何运行主要功能值得信赖成熟的专业技术团队及时的支持与帮助参考资料 JxBrowser 是一个商业跨平台 Java 库,可以让您将基于 Chromium 的网页浏览器控件集成到您的 …

【ES实战】ES中关于segment的小结

文章目录 ES中关于segment的小结ES中segment相关的原理在Lucene中的产生segment的过程。(Lucene commit过程)ES为了实现近实时可查询做了哪些缩短数据可被搜索的等待时长增加数据的可靠性优化segment的数量 段合并自动合并强制合并 相关配置translog合并…

Python 学习之路 03 之循环

😀前言 欢迎来到 Python 循环和流程控制的基础教程!无论您是一名新手,还是希望复习 Python 编程的基本知识,这个教程都是一个非常好的资源。在这份教程中,我们将探索 Python 中的不同循环结构和流程控制机制&#xff0…

火山引擎DataWind产品可视化能力揭秘

引言 BI是商业智能(Business Intelligence)的缩写,是一种将企业中现有的数据进行有效的整合的平台,它可以帮助企业、组织和个人更好地了解其业务状况、发现问题,并进行决策。BI产品普遍采用可视化的方式,可以帮助用户更直观、更高…

快速傅里叶变换

引言 目标 傅里叶变化(Fourier transform)是一种信号处理技术,它可以将时间信号转换为频率信号,即将一组具有相同数量频率的正弦波叠加在一起,形成一组新的正弦波。如果我们把时间信号从频域转换到时域,那么…

Drupal __ 8.5.0 __ XSS文件上传 __CVE-2019-6341

Drupal __ 8.5.0 __ XSS文件上传 __CVE-2019-6341 说明内容漏洞编号CVE-2019-6341漏洞名称Drupal XSS漏洞漏洞评级中危影响范围在7.65之前的Drupal 7版本中; 8.6.13之前的Drupal 8.6版本; 8.5.14之前的Drupal 8.5版本。漏洞描述Drupal诞生于2000年,是一…

PbootCMS在搭建网站

1、打开网站 https://www.pbootcms.com/ 2、点击 “本站” 下载最新的网站代码 3、在本地laragon/www下创建目录(hejuwuye),并将代码放进去 4、创建本地数据库,数据库名称为: hejuwuye,然后将static/bac…

25.Xaml DateGrid控件---->默认单选,可以多项选择的网格控件

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

深入理解JVM虚拟机第五篇:一些常用的JVM虚拟机(二)

文章目录 一&#xff1a;JRockit VM的介绍 二&#xff1a;J9 VM的介绍 三&#xff1a;KVM和CDC/CLDC Hotspot 四&#xff1a;Azul VM的介绍 五&#xff1a;Liquid VM的介绍 六&#xff1a;Apache Harmoney 七&#xff1a;Microsoft JVM 八&#xff1a;Taobao JVM 九&a…

第三方软件测试机构有哪些测试服务软件测试报告收费标准是怎样的?

软件验收机构 一、什么是第三方软件测试机构? 第三方软件测试机构是区别于软件开发公司以及软件需求方的第三方机构&#xff0c;软件企业将软件测试外包给第三方软件测试机构已经成为了行业发展趋势。既省心省力&#xff0c;又降低企业成本&#xff0c;得出的软件测试结果以…

【Proteus仿真】【STM32单片机】四驱寻迹避障小车

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 系统运行后&#xff0c;LCD1602显示红外、超声波检测状态和距离、小车运行状态。可通过K1键可手动切换模式&#xff0c;寻迹、避障、蓝牙遥控&#xff1b;也可通过蓝牙发送指令切换模式&#xff1b; 当处…

绝佳用户体验:构建响应式网页设计的关键原则

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 当谈到前端开发时&#…

使用Java创建一个简单的图书管理系统

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 图书管理系统项目简…

for...in...与for..of...

for...in... 仅迭代自身的属性for...in 语句以任意顺序迭代一个对象的除Symbol以外的可枚举属性&#xff0c;包括继承的可枚举属性。 for ... in是为遍历对象属性而构建的&#xff0c;不建议与数组一起使用&#xff0c;数组可以Array.prototype.forEach()和for ... of const …