点击上方“芋道源码”,选择“置顶公众号”
技术文章第一时间送达!
源码精品专栏
精尽 Dubbo 原理与源码 69 篇
精尽 Netty 原理与源码 61 篇
来源:http://t.cn/EwxzSFo
关于如何阅读开源社区源码,最近陆续有同学过来问我这个问题。前段时间,在HBase技术交流群里,大家也讨论过一些零散的方法,但都不系统。借着这个问题,我也认真回顾了一下自己所用过的一些方法,觉的有必要整理出来,供大家参考。
先选择合适的源码版本
因为不同的版本间的特性/流程方面存在较大的差异,阅读源码时选择合适的版本还是至关重要的。因此,需要先审视自己的需求:
“我阅读源码,是单纯的为了学习?还是希望在业务系统中更好的用好它?”
如果是前者,那完全可以选择最新发布或待发布的稳定版本。
如果是后者,则需要选择自己业务系统中正在使用的版本。
借助书籍或官方资料快速了解技术架构和关键特性
如果有介绍原理的书籍,可以先快速浏览一遍,粗略了解整体架构、关键特性。
这些信息也可以从官方资料中一探究竟,尤其是架构介绍相关的章节。
从快速试用开始加强自己对该项目的感性认识
先参考官方资料中的Quick Start章节,先学习如何使用,加强自己对于整体项目的感性认识。
这个过程,基本能摸清楚利用该项目"能做什么",以及"如何做"。当然,这里仅仅涉及了最基础的功能。
简单了解源码模块结构,而后从最基础的流程入手
快速了解源码的模块组成结构,以及每一个模块的主要作用。
这样有助于从源码结构上把握整体项目的轮廓,而后选择最基础的流程入手。
对于HBase而言,最基础的流程无非是如何建表以及如何写数据的流程。
学习一个特性要从了解配置和如何使用着手,同时建议阅读相关特性的设计文档或网上已有的源码解析文章
在学习一个特性时,也应该先从如何使用这个特性开始,接口如何被调用,关键配置有哪些,都是了解基础功能的基本起点。
接下来,可以先自己思考一下,这个特性如果由自己来设计,那整体思路应该是怎样的。
部分关键的特性/流程,在社区的问题单中,通常会有简洁的设计文档,这些文档能帮你理清方案的整体框架和思路。如果没有设计文档,那问题单中的Comments也是值得参考的。
当然,网上如果已经存在一些源码解析文章,也可以先参考一下,但好的文章往往是可遇不可求的。
如果在阅读源码之前,能够大致了解方案的思路,对自己会有很大的帮助,"瞎子摸象"式的阅读非常费时费力。
有一点需要强调一下:书籍或别人的文章中所描述的流程,在新版本中有可能已经发生了变化,因此,阅读时一定要带着辨证的思维。
摸清主线,避免过早陷入一些旁枝末节
刚开始阅读源码时,会遇到很多"好奇点":
这个算法居然实现的如此神奇?
这个数据结构怎么没有见过?
这个参数是干嘛的?
我自己也时常经不起这些"诱惑",陷于对这些细节的考究中,常常"离题"半天以后,才被拉回到主线中。
在阅读源码的时候,能遇到一些感兴趣的细节是好事,但建议先将这些细节点记录下来,等过完整体流程以后再回头看这些细节,避免过早陷入。
阅读源码过程中,通常需要动手做一些测试,此时,可以借助jstack工具(针对Java项目),它能为你提供如下有价值的信息:
线程模型
调用栈
调用栈信息可以帮你理清整体调用流程(另外,在定位问题时,jstack打印出的信息也时常可以发挥重要作用)。
重视阅读日志信息
在进程启动或运行过程中,一些关键的操作或处理,都会记录日志信息,因此,阅读日志往往是一条有助于理清流程主线的捷径。
(PS: 感谢范欣欣同学补充的此条建议,笔者在实践中也时常用到)
阅读源码过程中,同步绘制时序图,固化对流程的理解
好不容易摸清的主线,建议及时用时序图的方式固化下来,这样可以帮助自己快速回顾整个流程。
当然,除了时序图,还建议附带简单的文字性总结。
阅读源码过程中,不断发现或提出疑问,并且记下来
当理清了主线流程以后,要继续深入探索这些细节疑问点,这些点决定了你对整个特性/流程的理解深度。
掌握一个特性/流程的基本前提,就是需要自己解答自己提出的所有疑问。
对于一些"莫名其妙"或"匪夷所思"的设计,请一定要对照参考社区问题单中的描述信息、设计文档或Comments信息。
阅读源码过程中,遇到晦涩难懂的细节,如何应对?
此时,建议开启Debug模式,详细跟踪每一步的调用流程,Debug可以分两种形式:
远程Debug
本地Debug
对于HBase而言,相比于远程Debug,本地Debug似乎更难以理解了,因为我们所熟知的HBase部署形态就是分布式的,要对运行时的HBase集群进行Debug,自然采用远程Debug模式了。
其实,Debug也可以针对HBase提供的测试用例,大部分用例都是基于一个本地模拟的Mini Cluster运行的,这个Mini Cluster运行在一个进程中,使用线程模拟HBase的关键进程。
这个过程中,也可以动手小改一下源码,验证自己的想法,或者观察因为改动所带来的行为变化。
重视阅读测试用例源码
很多人并不习惯于阅读HBase的测试用例源码,其实,阅读测试用例的源码,可以帮你理解一些正确的行为应该是怎样的。
因为每一个被定义的正确行为,都以具体的测试用例固化下来了。
重视实际遇到的每一个Bug,每一个Bug都可以讲一个完整的故事
阅读源码过程中,自己提出的疑问,往往还不是最深刻的。最深刻的点,往往存在于所遇到的每一个Bug中。
对于Bug,很多人的态度往往是,能规避则规避之,集群只要能恢复正常,就不再有任何兴致去探究根因。
Bug往往是一些未考虑充足的边界场景,如果想探究Bug的根因,必然需要先摸清与之相关的所有流程,而后结合问题现象进行相关推理。一个Bug的前因后果,通常可以讲一个完整的故事。只有经过一个个Bug的历练,才能逐步成长为内核专家。
能力进阶:开始关注社区动态,或尝试为社区贡献Patch
关注社区动态,可以及时获知一些重要的Bugs或社区正在开发的大的Features。关注的方式包括但不限于:
订阅社区的Mail List
关注社区的问题单
如果感觉自己已经很好的掌握了源码,而且发现了部分设计不合理,或者是部分能力不完善(结合实际的业务需求),也可以主动为社区贡献Patch,对于大部分开源项目而言,都是非常鼓励大家贡献Patch的。
总结
本文主要从方法论的角度探讨了阅读开源项目源码的一些建议,供大家参考。这是第一个版本的内容,欢迎大家在评论中贡献自己的优秀实践方法,我可以继续完善它的内容,期望能够为更多人带来有价值的指导信息。
如果你对 Dubbo / Netty 等等源码与原理感兴趣,欢迎加入我的知识星球一起交流。长按下方二维码噢:
目前在知识星球更新了《Dubbo 源码解析》目录如下:
01. 调试环境搭建
02. 项目结构一览
03. 配置 Configuration
04. 核心流程一览
05. 拓展机制 SPI
06. 线程池
07. 服务暴露 Export
08. 服务引用 Refer
09. 注册中心 Registry
10. 动态编译 Compile
11. 动态代理 Proxy
12. 服务调用 Invoke
13. 调用特性
14. 过滤器 Filter
15. NIO 服务器
16. P2P 服务器
17. HTTP 服务器
18. 序列化 Serialization
19. 集群容错 Cluster
20. 优雅停机
21. 日志适配
22. 状态检查
23. 监控中心 Monitor
24. 管理中心 Admin
25. 运维命令 QOS
26. 链路追踪 Tracing
... 一共 69+ 篇
目前在知识星球更新了《Netty 源码解析》目录如下:
01. 调试环境搭建
02. NIO 基础
03. Netty 简介
04. 启动 Bootstrap
05. 事件轮询 EventLoop
06. 通道管道 ChannelPipeline
07. 通道 Channel
08. 字节缓冲区 ByteBuf
09. 通道处理器 ChannelHandler
10. 编解码 Codec
11. 工具类 Util
... 一共 61+ 篇
目前在知识星球更新了《数据库实体设计》目录如下:
01. 商品模块
02. 交易模块
03. 营销模块
04. 公用模块
... 一共 17+ 篇
目前在知识星球更新了《Spring 源码解析》目录如下:
01. 调试环境搭建
02. IoC Resource 定位
03. IoC BeanDefinition 载入
04. IoC BeanDefinition 注册
05. IoC Bean 获取
06. IoC Bean 生命周期
... 一共 35+ 篇