大家好,我是伟伟。上一篇不是经常让大家拉取源码,然后看代码提交记录吗?也就是说,看一个类似这样的界面:比如在上面的界面中,可以看到RedissonBaseLock.java这个文件,是谁在什么时候做了修改,修改对应的commit信息是什么。这样就可以直观的看到文件的演变过程。那么问题来了。有几个同学问过我这个问题:idea中如何查看git提交记录?这个接口隐藏在哪里?为什么它不在我的想法中?好吧,是我疏忽了。我先入为主,大家应该都知道这是怎么回事。但是确实有一些同学不是很清楚。在这篇文章中,我将通过这个东西来分享一个我用来阅读源码的小技巧,希望能对你有所帮助。怎么弄出来?那么如何把这个视图弄出来呢?首先,你必须在本地有一个git.exe。这件事是怎么来的,不用我多说。如果你没有这个,那就说明你之前没有接触过git,那就另当别论了,不在本文讨论范围之内。赶快安装一个git,然后学习如何使用git。我个人的习惯是先用gitbash,就是这个东西,从github上clone一个项目:比如我就用之前写的Redssion来做示范。你也可以找到任何你感兴趣的开源项目。执行以下命令下载项目:gitclonehttps://github.com/redisson/r...下载完成后,打开你的idea,导入我们刚刚下载的项目。然后随便打开一个文件,右击看有没有Git的选项:如果顺利,点击ShowHistory后,可以看到这个窗口:如果不顺利,说明有问题你的git配置。在idea的Settings中进行相应的设置:设置完成后,可以点击旁边的测试按钮。如果有弹窗告诉你对应的版本号,就说明配置成功了:总之只要能调用版本控制选项卡或者一些高版本调用git,就说明配置成功.你怎么认为?不管是在工作中还是在写文章的时候,我一般只是看看idea中的提交记录,而不会在idea中使用git来提交代码。其实idea中拉取代码和提交代码的可视化页面非常好,但是我还是比较喜欢在gitbash中直接敲命令,也没有什么特别的原因,但是看起来很逼真,很高端。那么,怎么看呢?以我之前写的Redisson文章为例。它主要是围绕RedissonLock.java类编写的。我怎么知道这门课?其实带着问题去debug肯定能定位到这个类,只是需要一点时间。曾经在搭建好环境后疯狂写casedebug。现在聪明多了,等环境搞定了,我就去github的issues,搜索关键词。比如我的关键词是deadlock:但是我强烈建议大家不要用中文搜索,用英文,deadLock:这样可以查到很多资料,剩下的你一个一个点进去看如果你遇到自己。问题相同或相似。这个过程会花一点时间,但绝对比潜入源代码寻找答案要快。比如上面的截图,最后一个叫DeadlockafterRedistimeout的issue就是我要找的:这里给出了复现代码,涉及的版本,预期结果和实际表现。比如我找到这个链接后,给我找了一个测试用例,他告诉我一个命令:CLIENTPAUSE5000之前,我并不知道这个命令。我一直在想,我在复现demo的时候,应该怎么模拟Redis执行命令超时的现象呢?我当时能想到的一些方案就是bigkey,或者往里面倒很多数据,然后我执行keys*命令,或者创建一个save命令,来模拟Redis阻塞。但是有工作量,阻塞时间不可控。而这条命令直接解决了我的问题,至少让我少走了一些弯路。同样,与此问题相关的还有其他几个问题,官方认为是同一个原因引起的:如何解决?一般来说,他们应该关联一个pr,通过这个pr,我可以直接链接到相应的修复内容。但是这次他们做了一个show操作,直接做了一个SNAPSHOT版本,跟pr:whatdoesnotrelated呢?这个时候我就想看看他是怎么解决这个问题的,怎么办?上述思路中的git插件就派上用场了。首先,我从他的评论时间知道是2019年3月13日,所以我可以直接在工具里定位当天提交的内容。单击版本控制视图中的日志选项卡,您可以看到整个项目历史中的所有提交。它会按照时间顺序给你排序,方便你找到当天相关的commit:如果你觉得很少见也可以直接按日期过滤:从当天提交的commit信息就知道我在找合适的地方。而这里我只是修改了RedissonLock.java这个类,所以找到了这个关键类:然后点进去分析这个类的具体修改,这样我发现debug的时候应该重点关注一下。再比如watchdog失效的bug:https://github.com/redisson/r...里面,直接关联了一个pr,然后我们可以通过这个链接找到提交的代码,就可以了也找到了它对应的issues。这件事是双向的。而且我也可以知道这个提交对应的类叫RedissonBaseLock.java:那我可以回到idea的视图直接看这个类的提交记录:发现这哥们一共提交了三倍。而且我还发现这个班比较年轻,2021年1月21号第一次投稿。我之前在文章《踩到一个关于分布式锁的非比寻常的BUG!》留了一个思考题:就是这三个投稿引起的。下面我带大家看看这三个提交是什么。首先是第一次提交,加入else分支,其中执行一次cancelExpirationRenewal方法,入参为threadId。包含是将当前线程的重入次数减一。但是能够走到else分支有一个大前提就是更新锁的lua脚本返回false,也就是锁没了。锁都没有了,为什么还要维护重入次数呢?只需直接从MAP中删除对象即可。如何删除它?传入null:就可以了,所以,有第二次提交,入参由threadId改为null:那么第三次提交是干什么用的呢?完全看不出它在做什么?别着急,我给你一张这样的截图你就明白了:我以前用的是制表符,后来改成四个空格了。这是编码风格的问题。说到是使用制表符还是空格,这是编程界争论不休的另一个话题。记得以前看过一部美剧,叫《硅谷》。里面的主人公为了用制表符还是空格与女友吵架。然后……写文章的时候想到了一个无聊的问题,就去找答案。想知道Redisson是什么时候引入watchdog机制的,想看看这狗一开始长什么样子。我是怎么找到它的?首先我知道启动watchdog的代码是RedissonLock.java中的renewExpiration方法:那么我可以通过RedissonLock.java的历史提交记录中的renewExpiration方法来查找第一次提交renewExpiration方法的时间时间。于是很快就找到了2019年3月13日这个时间:刚发现watchdog改了名字,之前叫scheduleExpirationRenewal,后来改名为renewExpiration。显然,我认为新名称更好。然后继续找scheduleExpirationRenewal第一次出现的时间。找来找去,发现了2015年12月14日的这个投稿:好家伙,这狗还有个以前的名字叫newRefreshTask。终于找到了newRefreshTask第一次出现的地方,也就是2015年7月4日:今天是watchdog的生日,距离今天还有不到两个月的时间,提前祝他生日快乐。但是,我不得不抱怨。关于这个看门狗提交,提交了很多东西。可以在本次提交上右击,然后点击下面加框的选项:可以看到本次提交的所有内容:提交了31个文件,包括watchdog机制。但是提交的commit信息很简单,因为涉及到事务操作,只是体现了LUA脚本的这个特性的使用。这是一个非常糟糕的提交示例。但是你再想一想,你每次提交的例子怎么写,是不是经常偷懒。别问我怎么知道的。所以,每次提交都要认真写好commit信息,因为你要知道,总有像我这样无聊的人,会挖出一些无用的知识点出来。比如我问你,我找到的这个看门狗机制的描述,除了让你知道它的生日和几个以前的名字外,还有什么用吗?是的,一点也不。恭喜你,又学到了一点没用的知识点。再给大家看一个项目,Dubbo。还是按照我前面说的,把项目拉下来,然后点击这里的log,可以看到整个项目历史上的所有提交:拉到最下面,可以找到历史上第一个提交:第一个submission是梁飞在2011年10月20日23:04提交的。但是从提交的commit信息中我们也知道这是一个空提交。真正的第一次提交是在2分钟后的23:06:9个模块,共669个文件,这就是这段颠簸路途,濒临死亡,续命的友商,最终成为顶级开源项目的雏形阿帕奇的。11年前的10月20日,梁飞从晚上23:00工作到凌晨5:25,终于给Dubbo打上了第一个里程碑:2.0.7。期间,他还发了一条微博:而他自己,在第二天中午,也在他的博客上公布了这件事:https://www.iteye.com/blog/ja...Dubbo为什么会选择这一天开源?我觉得应该是赶上两天后的Qcon全球软件开发者大会:那一天是Dubbo真正意义上的站在大众视野,接受褒贬的开始。在idea视图中,还可以过滤指定人提交的记录。比如梁飞用以下账号提交代码:我过滤了一下,发现多达1294次,最后一次提交是2015年4月1日:而且我也发现他很能干,类似这个时间点有几个提交记录:然后找了几个类,看看他的代码经过10多年的发展,这些类里还剩下多少。首先介绍一下这个负载均衡策略相关的类AbstractLoadBalance.java。右击这个类,然后选择git->Annotate,调出左边的(time-user)视图:这里显示当前类,谁提交了每一行代码,什么时候提交的。还能看到梁飞。还有我给大家介绍一下:这个方法就是在Dubbo启动的时候给新机器预热,稍微给点权重。第一分钟给10%的流量,第二分钟给20%的流量……第十分钟机器基本已经完全预热,可以给100%的流量。至于为什么需要预热,这个跟JVM有关。如果你有兴趣,可以研究一下。就是这个功能,这个核心方法,经过了10多年,除了有一点微调,它的核心算法和核心逻辑没有一点变化。再举个例子,给大家看一下最不活跃的负载均衡策略LeastActiveLoadBalance.java的实现:从最初提交到现在,没有修改过几次。但是你要知道每次提交都有它的意思,比如这两个:一个提交就是把变量leastIndexs改成leastIndexes,因为index是以x结尾的名词,以s,x,sh,ch结尾,它的复数的形式应该是加es。这是一点英语知识。一个提交是用ThreadLocalRandom代替Random,因为后者性能更好。这是编程知识,其背后的原因值得深挖。这取决于是否有爱心人士。也可以对比一下初始版本和现在最新版本,核心算法和核心逻辑基本没变:这两个类告诉我什么?与业务代码的增删改查相比,只有算法和稳定的算法更容易在时间的长河中生存,历久弥新。然后,再回到日志标签,你会发现一个很奇怪的现象。2014年到2015年,提交代码的次数不多:其实2013年到2017年,提交的次数基本不多。为什么是这样?这就不得不说到Dubbo坎坷的一生了。前面说了,2011年出身豪门,从阿里开开出来。但是在2012年10月23日Dubbo2.5.3发布后,阿里基本停止了对Dubbo的维护和升级。随后直到2017年9月7日,Dubbo在GitHub上悄悄发布了2.5.4版本。随后,2.5.5、2.5.6、2.5.7等版本迅速发布。在10月举行的云栖大会上,阿里宣布将Dubbo纳入集团重点维护的开源项目,这意味着Dubbo起死回生,开始重新进入快车道。从2012年到2017年的这五年,当当网拉了一个Dubbox的分支开始,相当于帮Dubbo活下去。2018年1月8日,Dubbo2.6.0版本发布。新版本合并了此前开源的当当网Dubbox,实现了Dubbo版本的统一整合。随后在2018年2月,阿里巴巴宣布将Dubbo捐赠给apache,进入apache孵化器。2019年5月21日,经过漫长的潜伏期,Dubbo迎来毕业。成为Apache基金会的顶级项目。之后的故事大家应该都知道了,Dubbo现在已经3.0了,准备在云原生的赛道上发力了。所以你看,这绝对是一个很酷的例程。这是一个富家子弟意外流落街头,被人收养,悉心照顾,最终在一片惊呼声中重回巅峰的故事。那么这个故事告诉我们什么呢?它告诉我们,有一个好爸爸真的很好。如果Dubbo没有被阿里开源,想起死回生是一件非常困难的事情,一半都已经消失在历史的长河中了。话说回来,上面说的这些东西都可以从我在这篇文章中给大家提到的idea的观点中推导出来。而我只是给大家介绍了一些很常见的用法,大家可以自己去挖掘更适合自己的顾虑。这个东西,我平时没事干,拉下一个自己感兴趣的项目,看看提交记录,再看看新特性。之前说过,每一个投稿都有它的意义,有的投稿是值得深挖的,就看有没有心人。你说,这东西不比小说好看吗?欢迎关注公众号为什么科技,第一时间收到最新文章。
