如何成为一个源码高手
大家好,我是yes。
从业多年,我研读过非常多开源项目的源码,比如:RocketMQ、Kafka、Dubbo 、Netty、Tomcat、Redis、Linux 、Spring 等等。
期间也有过迷茫,也走过很多弯路,今天就来分享一些心得体会,希望对大家有点帮助。
疯狂劝退
在实习时期,我非常羡慕组里架构师,他总能丝滑地帮助同事处理各种各样的问题,甚至于别的项目组的同事都经常来请教他。
我非常狗腿的黏在他身边,希望他传授一点“功力”给我,每天问东问西的,直到有天他跟我说:”其实这些东西不难,只要你多看看源码,知晓里面的原理,从报错就能直接看出问题所在。“
说出来不怕人笑话,我还去上网查了下。
查啥?查叫源码。
当天我就去下了 Spring 的源码,在打开源码那一刻,我血脉喷张,感觉自己立马就要成为人人敬仰的大牛。
背景音乐已经响起,却又戛然而止,妈的,idea 全飘红,项目如何启动我都不清楚,直接一脸懵逼。
花了一周的时间,idea 终于不红了,启动入口也找到了,背景音乐又缓缓响起,但是没过五分钟又焉了.....
我一阵点点点,从这个类跳到那个类,类中的方法又各种嵌套,每个类的名字我都念得出来,却是不知道它的作用,就这样迷失在 Spring 的类中。
不知所云,手足无措。
挣扎许久,终究化作一声叹息。
自我安慰道:算了,大牛让别人当吧,我当请教大牛的那个人,好好做绿叶该做的事情。
卷土重来
就这样浑浑噩噩的过了两年,从一个菜鸟,变成了一个——老了两岁的菜鸟。
摆脱了实习生的身份,但实际能力可能也就比实习生 CRUD 写的快一些。
没办法,虽然期间我也看了很多博客,学习的热情是高涨的,但是对知识的理解基本上是浮于表面的。
平时开会啥都能搭上话,但一要我分析让我说个所以然,就慌了。
心里没底,因为很模糊,很多时候说的头头是道,让我写P都写不出来或者说不敢写,心里对源码是惧怕的,总觉得自己的代码这么low,配不上非 CURD 的功能。
直到有天,同事向我请教消息队列的实现原理,由于天天在他前面装B,我拉不下脸说不会,只能被动的去学习去解答他的问题。
你别说,这效果杠杠的,果然人都是逼出来的。
不过这也是因为我打开了正确学习源码方式。
系统学习源码的方式
这内容我在 20 年分享过,这里再分享给星球的同学。
首先,我把 RocketMQ 官网、wiki 都读了一遍,了解具体涉及到的概念、名称、特性、架构。
对整体项目的主要角色以及之间的数据交互都了然于心,在脑海中形成了角色分布图和数据流转图。
当然也包括 RocketMQ 的功能使用,比如顺序消息发送的 api 要如何操作、事务消息怎么发的、如果消费消息等等。
在源码中提供了很多 demo,利用 demo 就可以非常快速地熟悉 api 的使用。
到这其实距离成功就差一半了,因为你已经打好了基础,且找到了突破口。
基础就是对这个项目的基本了解和功能熟悉,突破口就是这些 demo。
有了 demo 就有了 debug 的入口,你只要打好断点,debug 启动,一步一步跟下去。
这跟之前直接下源码看源码有区别吗?
当然有区别!
此时的你不像一只无头苍蝇到处乱啃,你是在知晓大体会涉及到的角色和数据流转之后读源码,这很不一样!
你会对一些方法调用有一种“认可感”,因为你知晓大致的流程,所以觉得本该如此,看完会有种,原来是这样实现的了然感。
读源码有时候会觉得代码很多,分支好多。
没事,代码在你本地,随意你修改,你可以先拷贝一份,然后把一些异常处理分支先删了。
核心流程先理清楚!
理清楚了一个流程之后开始画图,流程图、脑图都上。
然后反过来再把之前删减的异常代码补上,把异常部分也弄清楚,补充完整流程图、脑图等。
看看我之前分析 Kafka 的时候画的图,就类似这样的搞清楚一个流程:
然后这一模块就收工了!搞定!
接着各种其他流程模块发散出去,到最后大致的流程就都清晰了,源码也就读的差不多了。
读源码的时候肯定也会遇到一些不能理解的,先略过,主流程先搞懂。
搞懂整体核心流程之后可以抠一些细节了,比如我之前看 Dubbo 的时候就抠了一个细节:
就这个 if switch 能关系到底层 CPU 的分支预测!
再比如之前看 Kafka 的索引设计涉及到二分查找,但是源码中是改版的二分查找。把索引项分为热区和冷区,深究下去是为了避免缺页中断。
再比如 RocketMQ 里面看预热文件的时候涉及的这个方法。
这时候又涉及到 mlock、madvise 。
这些就是细节,而细节往往就是我们需要学习的地方,所以在理清整体流程之后不要错过细节。
往往你觉得很奇怪的地方可能就是一些“骚操作”,学的就是“骚操作”。
这是系统读源码的方法,是为了让自己得到晋升、学习优秀开源框架是如何设计而读的源码。
只要你攻克了一个,后续就能越读越多,越读越轻松。
为了找问题读源码的方式
有了系统读源码的基础后,你就能尝试上手去解决各种问题了。
比如,有时候是项目出错,一般而言有日志,所以通过日志搜源码就行。
如果你本身对这个框架很熟悉那当然最好,如果不熟悉通过日志搜索结合上下文其实也能找到一些缘由。
不过有时候还是得整个链路分析下来才能排查问题,这个看功力了。
有时候是因为看到一些文章的说法冲突了,一篇说 A 另一篇说 B ,如果你找不到权威的信息你只能自己去看源码,通过关键字搜。
比如我这篇写的:
这就是源码之下无秘密。
这种目的性很强的读源码就得结合当时上下文和靠个人功力了,这也是想成为大牛必须要掌握的一个能力。
最后
不知不觉说了这么多。
我只能告诉你不要被源码劝退,要自顶向下的看源码,不要一来就钻进细节,先从官网等渠道对开源框架有个全面的了解,然后看源码理清主流程。
再配合流程图、时序图、脑图等记录、归类。
然后再看细节,学学优秀开源框架的“骚操作”。
模仿它,学会它,从中能延展出很多额外的底层知识,比如上面提到的预防缺页中断,预热锁页,分支预测等等。
当然也可以先去网上搜一搜别人的源码分析文章,然后自己再上手,这样会比较舒服和顺利。
或者看一些相关的付费专栏,人家汇总整理知识,你花点小钱,节省你自己研究的时间,不亏。
还有,源码是块硬骨头这毋庸置疑,我只能告诉你看源码的准备工作和一些小心得。
最后,要抱着目的去学源码,比如你是想更进一步地去学习其中的原理,或想参考其实现解决工作上遇到的一些问题等等。
而不是为了学习源码而学习源码。
道阻且长,行则将至。
冲!
最后的最后,推荐下我在知识星球写的消息队列-RocketMQ专栏,各位小伙伴可以看看,如果有啥问题或者疑问欢迎提出!
这个专栏的定位是原理入门,系统学习下来对付一般的面试消息队列原理问题应该是ok的。
我是yes,从一点点到亿点点,我们下篇见~
