乐趣区

关于java:我给Apache顶级项目贡献了点源码

这是 why 技术的第 91 篇原创文章

这篇文章其实并没有什么技术性的分享,从我的角度而言,更多是记录和思考。

把我对于源码和之前写的局部文章反哺给我的一些货色,带来的一点点思考分享给大家。

一行源码

我很长时间没关上我的 Outlook 邮箱了。

前两天关上的时候发现我之前给 Dubbo 提交的 pr 竟然曾经被合并到 master 了:

这是第一次,我提交的 pr 被合并了。

这个 pr 是修复 LFU 缓存策略在 Dubbo 中即便配置了,也不起作用的 bug。

于是我也算是为开源我的项目奉献过源码的人了。

什么你问我奉献了多少代码?

一行,是的,就一行!

而且,说起来,这次提交真的是没有什么技术含量的事件。因为这是一个必现的 bug,只是很少有人用到这个性能而已。

你晓得的,当一个 bug 能稳固复现的时候,其实它曾经就不算是一个 bug 了。

然而我想聊聊这次提交背地的一些货色。

发现与解决

从宿命论的角度来说,当我写上面这篇文章的第一个字的时候,这个 bug 就注定是等着我去发现并修复了:

其实吧,LRU 也就那么回事。

而这篇文章我敲下第一个字的工夫是 2020 年 12 月的下旬,这是我 2020 年的最初一篇技术原创文章。

当我写 LRU 的时候,我就晓得 LFU 必定也是须要专门写一篇的。

于是 2021 年的第一篇技术原创文章,我就选题了 LFU。

产生了这篇文章:

哎,这让人抠脑壳的 LFU。

写这篇文章的时候,我想起之前看 Dubbo 的版本,如同是提到了一下 LFU。

于是我翻到了 2.7.7 版本的公布内容:

果然是反对了 LFU 缓存策略,于是翻出了提交的代码记录:

尽管他的实现逻辑没有问题,Test 类也跑过来了。

然而毫不夸大的说,我看了一眼这个提交记录,就发现了这里势必是有问题的。

他仅仅是把 LFU 缓存策略汇合到了 Dubbo 代码中,然而却没有给使用者提供应用的入口。

因为这里是基于 SPI 实现的,他没有在对应的配置文件中退出配置。

这个问题非常容易验证,咱们能够看一下。

其源码的地位是:org.apache.dubbo.common.utils.LFUCache

源码外面通知我这样配置一下就能够应用 LFU 的缓存策略:

然而,当我这样配置,发动调用之后,是这样的:

能够看到以后申请的缓存策略的确是 lfu。

然而会抛出一个谬误:

No such extension org.apache.dubbo.cache.CacheFactory by name lfu

没有 lfu 这个策略。

这不是玩我吗?

再看一下具体的起因:

org.apache.dubbo.common.extension.ExtensionLoader#getExtensionClasses 处只获取到了 4 个缓存策略,并没有咱们想要的 LFU。

所以,在这里抛出了异样:

为什么没有找到咱们想要的 LFU 呢?

那就得看你熟不相熟 SPI 了。

在 SPI 文件中,的确没有 LFU 的配置:

所以,这是个 Bug,而这个 Bug 的解决方案,就是在 SPI 文件外面加上一行 LFU 的配置即可。

通过下面的剖析,其实你也发现了,这个并不是一个有什么技术含量的提交。

更多的是运气成分。

只是因为对于 Dubbo 框架有些许的理解,所以对于这个中央,我发现问题、定位问题、解决问题的速度十分的快。

这是运气带不给我的货色。

这须要日复一日的潜入到框架中去,去感触它的脉络,梳理它的构造,学习它的思维。

这是须要工夫去积淀和学习的货色。

留神,我说的是“潜入”,而非是流于外表的。

什么是流于外表的呢?

比方,如果你之前没有用过 Dubbo 框架,但你又想去理解,学习它。

于是你看到了我的这篇或者其余的和 Dubbo 相干的公众号文章,希图从这些文章中动手。

记住鲁迅学生的话:

亦或者是你在搜寻框外面,输出“Dubbo”,而后漫无目的的看了起来。

哪怕你买了一本 Dubbo 相干的书或者看了 Dubbo 相干的系列视频,进行零碎的学习。

我感觉,只有没有本人亲手去做,都属于流于外表。

而本人入手的第一步,就是搭建 Demo,从 Demo 动手。

到前面高阶一点的就是你理解到了这个框架的前世今生,能在几个大版本之间进行横向比照,晓得为什么降级、怎么降级、降级之后是怎么样的。

再之后,能粗疏到某一个大的模块的演变是怎么的,历史上呈现过哪些 Bug,是怎么去修复的。在那个版本之后进行了修复,是稳固的。

再举个例子吧。

另外一个 bug

回到最开始的中央,我为什么会在写 LFU 的时候联想到 Dubbo 呢?

因为在 2.7.7 这个版本公布的时候,我就关注到了它。

而过后关注到它的起因并不是 LFU,而是新增了一种负载平衡策略:

于是我把之前的文章进行了汇总,写下了这篇文章:

吐血输入:2 万字长文带你细细盘点五种负载平衡策略。

而其中一致性哈希负载平衡策略,我在实际的时候也发现了一个 bug。

其实这个 bug 也是一个必现的 bug,为什么没有被爆进去的起因,我想是因为以后的版本应用的人不多,而应用一致性哈希负载平衡策略的就更少了,甚至没有。

这个 bug 具体是这样的:

https://github.com/apache/dub…

我曾经晓得了在一致性哈希算法中的这行代码就是导致 bug 的起因:

System.identityHashCode(invokers)

甚至我也晓得了,这行代码导致 bug 的起因是 invokers 这个汇合的地址变了。

这个汇合外面,放的就是服务提供者列表。

汇合外面的服务者列表其实并没有变动,只是每次都用了一个新的 list 来装这些服务提供者。

而为什么每次都用一个新的 list 来装,我也找到了:

问题就出在 TagRouter 中:

org.apache.dubbo.rpc.cluster.router.tag.TagRouter#filterInvoker

基本上到这里,也就明确起因了。

然而我后面说了,更高一级的是理解这个框架的前世今生。

问题出在 TagRouter,那么这个 TagRouter 怎么来的呢?

如果理解 Dubbo 2.7.x 版本新个性的敌人可能晓得,标签路由是 Dubbo2.7 引入的新性能。

巧就巧在我还真的分明这个中央的前因后果。

因为我的第一篇技术文章就是写的 Dubbo 2.7 新个性,过后进行了一个理解。

没想到一年多当前,居然还响应上了。

而这个 bug,其实也是一行代码就能修复;

而我过后为什么没有去修复呢?

因为最开始找到这个 bug 的时候,我想到的解决方案是写个工具类。

思路也是只关怀 List 外面的元素,而不关怀 List 这个容器,然而实现形式比较复杂,改变点较多,还须要写一个工具类。

过后就没入手,想着先提个 issue 放着,有工夫了再弄。

后果,没想到 issue 放上去的当天就有人回复并了一个我没有想到的解决方案:

看到这个回复的时候,我才一下回过神来,原来一行代码就能代替我写的工具类了啊。

而对于其中波及到的知识点,我是晓得的。

我反思了一下本人为什么没有想到这个计划。

其实就是对于已晓得的知识点,把握不够粗浅导致的,没有达到死记硬背的境地。

知其然,也知其所以然,惋惜在须要应用的场景稍稍一变的状况下,就想不起来了。

晓得知识点,然而该用的时候却记不起来,这种状况其实挺常见的,那怎么解决呢?

于是我写下了这篇文章:

够强!一行代码就修复了我提的 Dubbo 的 Bug。

这篇文章就是我的解决方案,记录下来嘛。

就像高中的时候人手一本的错题本,做错的题,不会的题都抄下来嘛。没事的时候翻一翻,总有下次碰到的时候。再次碰到时,就是“一雪前耻”的机会。

写过但没有发现的 bug

我之前还写过一样的一篇文章:

Dubbo 2.7.5 在线程模型上的优化

过后这个版本推出之后,我就连忙去钻研了一下对应局部的源码,而后写下这篇自称为全网第一篇解析 Dubbo 2.7.5 里程碑版本中的改良点之一:客户端线程模型优化的文章。

然而前两天我看提交记录的时候,发现了这样的一个提交:

并找到了对应的 issue:

https://github.com/apache/dubbo/issues/7054

依据这个 issue,我去看了一下对应的源码,的确是存在他形容的问题。

于是我就在想,我过后写文章的时候也是深刻到源码外面了呀,为什么没有发现这样的问题呢?

我想起因还是在于本人过后思考的深度不够,仅仅是搭建了一个十分简陋的 Demo,而且把心理聚焦到了前后版本差别比照上。

只是摸到了一个大略的样子,被源码牵着走了,并没有跳出源码的突围,带着质疑的眼光去扫视它。

所以,对于这种比拟深层次的、一环扣一环的问题,本人还是流于外表了一些。

怎么看源码

后面举了三个例子,一个是发现并解决了 bug,一个是仅发现未解决的 bug,一个是有 bug 但没有发现。

前两个 bug 都有一个共性,在简略的 Demo 下就是必现的,只有跑到了对应的中央,就会呈现和预期不符的状况,比拟容易发现。

最初一个 bug 暗藏的比拟深刻一点,兴许你触发了,然而程序自愈了。

当有一天我能发现并解决这样的 bug 时,我就不会说这是运气了。

然而发现这些 bug 的前提是得入手搭建 Demo 呀。

你不看源码,只是看网上的文章,是永远发现不了问题的,也是潜入不进去的。

分享一下我看源码的办法吧。

咱们晓得开源框架的设计和理念大多是十分优良的,然而源码外面的细枝末节特地的多,一不小心就容易在源码外面迷失,间接就是一波劝退。

所以,对于初读源码的同学,首先要做的就是把外围流程梳理进去,边梳理边画图,要多画图,别怕麻烦。

对于几处要害的源码,肯定要写上本人的备注。因为你晓得的,过后兴许你对这个中央为什么这样写门清,然而隔段时间再回来看,就摸不着头脑了。这个时候,备注就显的十分重要了。

对于看不明确的中央,打断点,疯狂的调试,重复的调试。

期待主流程摸清楚之后,再去进入到源码的细节局部。

举个简略的例子,比方你看 Dubbo 源码,先摸清楚它一次申请大略的调用链路之后,再去粗疏理解其中负载平衡的局部。

而后,就是多温习,多坚固了。

你发现没有,我说的这些其实你也晓得,或者其他人也是这样说的。

为什么你看的时候就老是看不进去呢?不得要领呢?

是的,我开始也是这样的。然而,无它,唯重复练习尔。

共勉之。

最初说一句

满腹经纶,难免会有纰漏,如果你发现了谬误的中央,能够在后盾提出来,我对其加以批改。

感谢您的浏览,我保持原创,非常欢送并感谢您的关注。

退出移动版