你也對閱讀源碼感興趣,說說我是如何閱讀Nacos源碼的
前言
最近寫了一些列的Nacos源碼相關(guān)文章,很多朋友都感興趣的在問:你最近在閱讀什么源碼,如何閱讀源碼?今天這篇文章就以Nacos源碼閱讀來展開聊聊。對閱讀源碼或技術(shù)感興趣的朋友,也可以添加微信交流(微信號:zhuan2quan)。
在讀這篇文章的時候呢,要看你想獲得什么了。因為這篇文章亦是在寫如何閱讀Nacos源碼,也是在寫如何閱讀源碼。不要被技術(shù)棧所束縛,要提煉屬于自己的方法。看你所欲,取你所需。
閱讀源碼的目的
不清楚大家為什么要閱讀源碼,就聊聊個人閱讀源碼的目的,或許可以拿來借鑒。
學(xué)習(xí)底層原理與實現(xiàn)
閱讀某一個框架的源碼,最重要的目的就是更深入的學(xué)習(xí)它的底層實現(xiàn)及原理。這里的底層實現(xiàn)和原理相對來說要宏觀一些,比如閱讀Nacos源碼我就是想知道,它是如何實現(xiàn)服務(wù)注冊、服務(wù)發(fā)現(xiàn)以及那些服務(wù)實例是如何存儲的。
像文章《微服務(wù)的靈魂擺渡者——Nacos,來一篇原理全攻略》便是來源于此類閱讀。你也可以像我一樣,閱讀之后繪制成流程圖、架構(gòu)圖、數(shù)據(jù)結(jié)構(gòu)圖,甚至整理成文章等幫助自己學(xué)習(xí)和理解。
學(xué)習(xí)優(yōu)秀的代碼設(shè)計
這一項包含的點(diǎn)就太多了,比如架構(gòu)設(shè)計、功能實現(xiàn)理念、優(yōu)秀代碼示范、設(shè)計模式、算法等等。凡是能看到的,比較優(yōu)秀的實踐,都可以學(xué)習(xí)。
以Nacos為例,簡單的一個實例注銷的入口方法,你能看到多少值得學(xué)習(xí)的內(nèi)容?

上圖是我一眼看過去,代碼給我最直觀的感受。然后就可以對照自己項目中的代碼,思考一下是否能夠達(dá)到這么高的標(biāo)準(zhǔn)?是否能進(jìn)行改造?
再看一個Nacos Client中的例子,在Client中調(diào)用Server的API時,會涉及到重試機(jī)制和多個Server選一個進(jìn)行注冊的邏輯。看看Nacos是如何實現(xiàn)的。

暫且不說算法的優(yōu)劣,看到這里是不是感覺又學(xué)到了一種實現(xiàn)?而且你也知道了Nacos Client在調(diào)用Server時到底是怎么處理請求重試和異常的。有意思吧。
當(dāng)然,這個層面還有一些更深入的,比如一致性算法等很多解決方案的內(nèi)容。
學(xué)習(xí)知識點(diǎn)的運(yùn)用
這一項就更細(xì)碎更多了。像前面寫的《Nacos中已經(jīng)有Optional使用案例了,是時候慎重對待這一語法了》和 《Nacos源碼中為什么使用了String.intern方法?》都是在閱讀源碼時發(fā)掘的知識點(diǎn)。
這個層面有一個很好的點(diǎn)大家一定要把握住。那就是你可能看過很多文章在寫某個知識點(diǎn),而且也寫了一些簡單的實例。但如果你沒有實踐的機(jī)會,或者沒在大型項目中運(yùn)用,看源碼中的實現(xiàn)和思考就非常有意思了。
比如Nacos中對String.intern方法的使用,就沒你想象中的那么簡單。而且深入思考一下,還會發(fā)現(xiàn)并不是每個場景都適合,只有在字符串變化不大的情況下才適合緩存到常量池中。
這里再舉一個Nacos中對常見知識點(diǎn)的運(yùn)用,看看咱們思考的維度是否一樣。ServiceManager中有下圖這么幾個成員變量:

上面的知識點(diǎn)可能你已經(jīng)背的滾瓜爛熟了,但你見過怎么用么?你見過怎么結(jié)合起來使用嗎?怎么支持分布式、高并發(fā)的場景嗎?
只要你仔細(xì)分析一下,閱讀一下源碼的實現(xiàn),你就能得到答案,也算是一次實踐。
從源碼中可學(xué)的內(nèi)容太多了,我這里就不逐一講解了,后面會逐步形成系列文章的形式把我看到的源碼中的技術(shù)和思想分享給大家。
如何閱讀源碼
有了閱讀源碼的目標(biāo),下一步就是執(zhí)行了。這里就分享一些我閱讀源碼的方法,不一定適合你,但可以參考和改進(jìn)。這里全部以Nacos為例,后續(xù)不再做特殊說明。
代碼的下載
開源項目可以直接拉取源代碼,Nacos的源代碼有兩個平臺可以獲取:GitHub和碼云。碼云庫作為同步,定時更新。這里采用GitHub作為源碼來源,說不定啥時候還可以貢獻(xiàn)一些代碼。
可以直接執(zhí)行g(shù)it命令拉取開源庫代碼:
git clone [email protected]:alibaba/nacos.git
但個人并不建議這樣直接拉取代碼,可以從nacos的倉庫fork到自己的GitHub賬號下。這樣既可以保持與主干的同步,又可以方便的修改一些內(nèi)容。
項目結(jié)構(gòu)
下載完成之后,直接通過IDEA打開項目,待依賴類庫引入完畢,可看到如下項目結(jié)構(gòu):

此時可以大概了解一下目錄結(jié)構(gòu),基本都能見名知意。
address:地址服務(wù)相關(guān);
api:naming和config的api抽取;
auth:權(quán)限控制相關(guān);
cmdb:支持對接第三方CMDB獲取CMDB數(shù)據(jù)等;
client:為客戶端代碼;
common:共用工具類;
config:Nacos配置中心的實現(xiàn);
consistency:一致性實現(xiàn);
console:Nacos控制臺相關(guān)實現(xiàn);
console-uri:控制臺UI部分實現(xiàn);
core:屬性加載,初始化,監(jiān)聽器相關(guān);
distribution:發(fā)布相關(guān);
example:示例;
istio:對istio的支持,如k8s等;
naming:Nacos的核心功能,動態(tài)服務(wù)發(fā)現(xiàn);
項目的啟動與測試
要閱讀源碼跟蹤流程,肯定要先把項目啟動起來。由于Nacos是基于Spring Boot來構(gòu)建的,只需執(zhí)行對應(yīng)入口類的main方法即可。
在console項目中,執(zhí)行Nacos的main方法即可啟動項目。Nacos默認(rèn)啟動的是集群模式,研究代碼先啟動單機(jī)模式即可。這里通過在main方法中添加參數(shù)指定單機(jī)模式:
public class Nacos {
public static void main(String[] args) {
// 通過環(huán)境變量的形式設(shè)置單機(jī)啟動
System.setProperty(Constants.STANDALONE_MODE_PROPERTY_NAME, "true");
// 通過環(huán)境變量的形式設(shè)置關(guān)閉權(quán)限校驗
System.setProperty("nacos.core.auth.enabled", "false");
SpringApplication.run(Nacos.class, args);
}
}
程序啟動之后,在client項目中的單元測試(test)中可以看到NamingTest和ConfigTest類,直接執(zhí)行單元測試中的方法即可連接剛啟動的Server進(jìn)行代碼跟蹤調(diào)試了。
此時,關(guān)于不同API的操作,也可參看官方文檔的說明進(jìn)行調(diào)用驗證了,這就不做演示了。
項目流程的梳理
完成了代碼的下載和啟動之后,那么如何來梳理源代碼的業(yè)務(wù)邏輯呢?很多朋友可能會遇到一些困惑,比如看不懂,或看了就忘了,每次都得重新梳理一遍。
這個種狀況在初期階段很容易出現(xiàn),也算是正常情況。我的處理方式是,先將fork的代碼打一個分支(branch),比如我會打一個comment的分支。在這個分支上,每看到一行代碼有點(diǎn)難度的代碼或者需要備注的代碼,就會在上面添加注釋。
關(guān)于Nacos本人fork的代碼地址https://github.com/secbr/nacos,其中comment分支中在逐步添加注釋,對Nacos源碼感興趣的朋友可以看一下。

比如上圖是client請求服務(wù)器進(jìn)行注冊的部分代碼邏輯,我會將梳理過的路徑通過注釋的形式進(jìn)行描述。這樣每次看到就不用再次梳理了。
當(dāng)對上述邏輯看得多了,也就不會忘記了。就這樣逐個邏輯,逐個類的添加注釋,當(dāng)享受梳理流程圖或架構(gòu)圖時,只用將注釋內(nèi)容進(jìn)行提煉和概況即可。
再看一下client注冊時,server對應(yīng)的代碼注釋:

至此,關(guān)于閱讀源碼的核心部分已經(jīng)完事。剩下的就是逐個業(yè)務(wù)流程的梳理,逐個技術(shù)點(diǎn)的學(xué)習(xí)。如果遇到無法理解的部分,最好通過debug模式跟蹤一下,看看執(zhí)行到此處時,具體的數(shù)據(jù)都是什么。
小結(jié)
個人覺得閱讀源碼是每個程序員必備的技能,也是站在巨人肩膀上提升自己的必要手段。只有看得更多,才知道什么是更好的寫法和實現(xiàn)。當(dāng)然,每個人現(xiàn)階段的能力有限,有很多技術(shù)點(diǎn)或設(shè)計思想當(dāng)前階段可能無法看到,但不要緊,你也可以拿我來做個墊背的,畢竟我是計劃寫一個源碼解析系列的。
往期推薦
如果你覺得這篇文章不錯,那么,下篇通常會更好。添加微信好友,可備注“加群”(微信號:zhuan2quan)。
和花一輩子都看不清的人,
注定是截然不同的搬磚生涯。



