RocketMQ 的设计理念与源码阅读技巧
- 一、设计理念
- 二、源码设计
- 三、源码阅读技巧
一直想仔细仔细看看这个 RocketMQ 的源码,学学它的设计思想和编码风格,没准在以后自己在设计和编码的时候有思考的方向。这是专栏的第一篇 —— 介绍下 RocketMQ 的一些设计,懂其设计和原理,才能更好地阅读源码.
RocketMQ 是阿里巴巴开发的,开发之前他们也使用过当时流行的 Kafka 作为自己的解决方案,但是是说它没法满足低延迟、高可靠的要求(Kafka 若分区多了,对磁盘写来说会出现大量随机写的情况,写入性能会下降很多,这里说的低延迟与实际使用方式和数据存储实现有关系),当然还有其它原因,所以它们决定开发一款新的消息传递引擎来满足自己的业务需求。
上面内容来自:RocketMQ 官方文档
一、设计理念
咱先聊聊设计一款消息中间件需要具备的要素,设计一款消息队列中间件,首先它需要对外提供通信路口,提供生产、消费消息的路口,即需要具备网络通信能力;其次就是它得具备数据存储的能力,这数据包含消息本身与元数据存储。
了解完设计消息队列的必要元素,咱来看看 RocketMQ 的技术架构:
主要由四部分组成:
- NameServer
- 被用来当做信息管理的"注册中心",主要是用来管理元数据(路由信息)。Kafka 元数据管理是用的 Zookeeper,而 RocketMQ 是自己写了一个服务实现这个元数据注册中心,写的这个服务被称为 NameServer,NameServer 被设计出来是一种无状态的,即 NameServer 集群之间是不通信的,这样做一方面可以满足实际需求的前提下(路由信息无需保障集群之间强一致性,可以容忍分钟级别的不一致),相比 Zookeeper 性能也有极大的提升。
- Broker
- 主要用来做消息存储的服务
- Producer、Consumer
- 消息队列的客户端,除了实现消息的发送消费外,RocketMQ 很多功能交给了客户端进行实现,减轻消息中间件的实现复杂度,像消息生产的高可用、消息顺序消费、消费幂等等等,这些功能都是交由客户端实现的。
二、源码设计
看源码第一步就是下载源码:https://github.com/apache/rocketmq
随后了解一下源码的目录结构:
RocketMQ核心目录说明如下:
- acl:权限控制模块
- broker:broker模块(broker启动进程)
- client:消息客户端,包含消息生产者和消息消费者相关类
- common:公共包
- dev:开发者信息(非源码)
- distribution:打包分发目录(非源码)
- example:RocketMQ示例代码
- filter:消息过滤相关基础类
- logappender:日志实现相关类
- logging:自主实现日志相关类
- namesrv:NameServer实现相关类(NameServer启动进程)
- openmessaging:消息开放标准,已发布
- remoting:远程通信模块,基于Netty
- srvutil:服务器工具类
- store:消息存储实现相关类
- style:checkstyle相关实现
- test:测试相关类
- tools:工具类,监控命令相关实现类
RocketMQ 的网络通信是基于 Netty 实现的,这里需要提一下它是如何设计接收网络消息去执行任务的,如何进行的编码设计使得它更具拓展,更灵活。
其实在服务端(NameServer、Broker)/客户端(Producer、Consumer)中都维护了一个 processorTable,是一个 k-v 集合,key 是服务码 requestCode,value 是对应的执行单元 Pair<NettryRequestProcessor, ExecutorService> 类型,包含了处理 Processor 和执行线程的线程池。里面对应内容在对应业务系统启动的时候会自行注册。
客户端发送网络包的时候会携带 RequestCode,服务端接收网络包后进行解码得到 RequestCode,然后通过 ProcessorTable 找对应 Processor 任务拿对应线程池进行执行,从而实现了异步任务执行。这种服务注册机制,简洁且灵活。
类似这种使用 Netty 实现通信然后与业务结合的编码设计,我在 IM 系统、货柜系统也看见过。
三、源码阅读技巧
- 先理解相应底层原理,再去针对性的看源码实现,学习编码,验证原理
- 源码阅读建议起始点
- Broker 启动:BrokerStartup#start、NameServer 启动:NamesrvStartup#start、客户端相关的源码阅读可以从 example 目录下的用例直接入手
- 不太建议 Debug 阅读源码,建议静态看源码,看不懂的地方再尝试调试跟进。一方面是对这种能力的培养,另一方面中间件源码不同于业务系统,中间件源码堆栈太多,容易绕晕,而且很多异步
- 书籍与博客辅助看源码
- 书籍推荐:《RocketMQ 技术内幕》
- 反复看