0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

閱讀開源項目源碼的實用技巧(上)

jf_78858299 ? 來源:labuladong ? 作者:labuladong ? 2023-04-12 11:34 ? 次閱讀

本文分享一下在使用或者學習開源項目源碼的過程中的一些經(jīng)驗技巧。

因為我最近在研究 Apache Pulsar 這款消息隊列,所以就以這個項目為例, 不過本文介紹的都是通用的技巧,完全可以用在其他大型開源項目中

下面就來具體介紹一些技巧,主要分兩部分:

第一部分是文檔篇,即能夠哪里能夠獲取有效的信息解決問題;

第二部分是實操篇,即如何高效打斷點或借助工具理解源碼。

一、文檔檢索技巧

想學習了解一個開源項目,文檔可以幫我們解決大部分問題。當然我這里所說的不單單指官網(wǎng)文檔,還包括 issue、PR、源碼中的注釋和單元測試,這些地方都可以獲得大量有用的信息,所以我把它們統(tǒng)稱為文檔,下面我們從最簡單的開始。

1、官網(wǎng)文檔,著重 quickstart 和 concept 部分

官網(wǎng)文檔無疑是最權威的資料來源,不過官網(wǎng)文檔的問題是內(nèi)容太多太全面,適合遇到問題或需求時當做功能手冊去查閱。

所以官網(wǎng)的內(nèi)容需要選擇性地學習,我建議優(yōu)先著重兩個部分:

一是 quickstart 部分,也就是教你如何快速部署一個 demo 服務;二是 concept 部分,也就是名詞解釋、核心功能介紹等內(nèi)容。

快速部署 demo 服務不用說了,是我們學習新技術的第一步,一般會被放在文檔的第一章;而功能/名詞的解釋是我們接下來順暢地學習進階資料或參與社區(qū)討論的重要鋪墊。

對 Pulsar 這樣一個消息隊列來說,收發(fā)消息顯然是核心功能,所以官網(wǎng) Concepts and Architecture 部分中的 Messaging 章節(jié)顯然是很重要的,詳細介紹了 Pulsar 中諸如訂閱模式、死信隊列等關鍵功能:

圖片

我在前文 Apache Pulsar 架構設計 介紹到 Pulsar 采用存算分離的架構,存儲層依靠 Apache Bookkeeper。所以如果你的目標是學習 Pulsar,那么 Bookkeeper 的官網(wǎng)文檔也是需要閱讀的,因為 Pulsar 中的很多功能都會和 Bookkeeper 交互。

可以在本地啟一個 Bookkeeper 集群用 client 玩一玩,閱讀了解一下 Bookkeeper 中的專業(yè)術語,有助于理解 Pulsar 中的一些設計。

2、看完文檔看單元測試用例,輔助我們準確理解每個功能的預期行為 。

一般成熟開源項目的測試用例比較完備,會覆蓋所有關鍵功能的預期行為,所以單測用例其實也是很好的學習資料,和文檔搭配食用效果最佳。

比方說,有時候文檔用文字描述某個功能可能會比較繁瑣,讓人看的云里霧里,又或者文檔中并沒有介紹一些技術設計的細節(jié)。

遇到這種情況,我們大概率可以在單測文件中找到對應的功能測試代碼,根據(jù)測試代碼很容易反推功能,正所謂「talk is cheap, show me the code」。

舉個例子,有一次我看到 consumer 打出一條關于epoch的日志,我在分布式選主的場景倒是聽說過這個名詞,不過顯然消費消息和分布式選主沒什么關系,所以這個epoch到底是干什么的?

文檔里沒找到答案,這應該是一個具體實現(xiàn)中的術語,所以我就在源碼中搜索包含testEpochepochTest這兩個關鍵詞的函數(shù)名,發(fā)現(xiàn)了幾個測試用例:

圖片

PS:測試函數(shù)名的 test 關鍵字可能在開頭也可能在最后,所以需要都搜一下。

瀏覽了一下這幾個測試用例的內(nèi)容就大致理解了,原來這個epoch是消息重投遞功能(redelivery)中的一個術語,主要用于防止重復消費消息。

3、善用 GitHub,從項目的 issue/PR/wiki 列表獲取有效信息 。

首先,issue 列表不用多說了,如果你在使用軟件的過程中遇到了問題,首先考慮的就是去 issue 列表搜索。

雖然有時候搜出來的并不是直接的答案,但多換關鍵詞搜幾次,大概率就能找到一些思路解決問題了。

另外, PR 信息可以幫助我們了解某些代碼片段的上下文背景

舉個例子,比如你閱讀某段代碼時有疑惑,不明白這個代碼的目的是什么,那么可以在 IDEA 中的代碼左側單擊右鍵,打開「Annotate with Git Blame」就可看到這段代碼是誰在什么時候添加上去的:

圖片

然后把鼠標懸停在作者昵稱上兩秒,就會彈出這個代碼被合進 master 分支時的 PR 標題和鏈接:

圖片

18260就是這個 PR 的編號,點擊即可跳轉到對應的 PR 頁面:

圖片

可以看到這個 PR 是用來修復18241號 issue 的,在18241號 issue 中詳細描述了 bug 信息及復現(xiàn)方法:

圖片

有了這些上下文信息,就可以避免我們閱讀源碼時的障礙了。

最后, wiki 頁面可以幫我們了解一些重要的功能設計或改動 。

拿 Pulsar 來說,如果需要做比較重要的改動,需要提出一個 PIP 提案(Pulsar Improvement Proposal),也就是一個專門講解背景信息、設計思路的文檔。

而這些 PIP 文檔就收集在 wiki 頁面:

圖片

所以在了解某個功能模塊的設計思路時,可以先去 wiki 頁面看看是否有相關的 PIP 可供參考。

比如 Pulsar 的事務實現(xiàn),就有一個專門的 PIP 詳細介紹了設計思路,結合 PIP 的思路指引去學習源碼就會容易很多:

圖片

我個人覺得,好的 PIP 結合源碼,帶我們把一個功能從討論設計做到落地實現(xiàn),這就是很好的教科書呀,多花精力去研究,肯定會有所收獲的。

以上就是最常用的有效信息的獲取途徑,如果你在學習使用開源項目時遇到問題,那么可以嘗試上述的方法去尋找答案。

當然,熟練掌握進行信息檢索的工具進行高效檢索也是重要的技能,比如說 IDEA 的各種搜索、GitHub issue/PR 的搜索語法,這些技巧網(wǎng)上可以很容易搜到,我就不贅述了。

二、源碼閱讀技巧

想真正了解一個項目,看源碼肯定是逃不掉的一環(huán)。閱讀源碼的好處不用多說了,但閱讀源碼肯定會花費大量時間,而且這個過程不會很輕松。

你想嘛,成熟的開源項目經(jīng)過多年的發(fā)展,功能不斷演進,很多人往里面寫過代碼,恐怕沒人能保證自己完全了解系統(tǒng)的每個細節(jié)。我們閱讀源碼,就好比探索一座龐大的城市,很容易迷失在某個犄角旮旯。

對于這個問題,我可以分享一些小技巧。

技巧一、不建議看「死代碼」,建議在調(diào)試實際問題的過程中理解代碼 。

換句話說,不要拿著代碼硬讀,最好是通過動態(tài)調(diào)試來研究每個功能中做了什么。

拿 Pulsar 舉例,我們可以在命令行啟動 standalone 模式的 Pulsar broker:

$ bin/pulsar standalone

然后用 Java client 創(chuàng)建一個 producer 發(fā)送一條消息:

PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar://localhost:6650")
        .build();

Producer<byte[]> producer = client.newProducer()
        .topic("testTopic")
        .create();

MessageId messageId1 = producer.send(("hello1").getBytes());

client.close();

我們就可以調(diào)試這個簡單的場景,看看 producer 是如何創(chuàng)建的,消息是如何發(fā)送并存儲在 Pulsar 中的。

但如果想跟蹤調(diào)試這段代碼,會遇到一些問題:

第一個問題是,我們自己的項目是通過 Maven 引入 client 包的,如果進入這些包看到的是反編譯的 class 文件,無法直接看到源碼。就算 IDEA 可以直接幫我們下載源碼,但如果我們在從事 client 的開發(fā),需要 master 分支的最新版代碼,這和上傳到 Maven 的源碼還是不一樣。

這個問題比較容易解決,我們直接從 GitHub 下載源碼,在 client 包里面創(chuàng)建一個 test 文件寫邏輯,這樣就可以調(diào)試最新的 client 代碼了。

第二個問題比較棘手,我們想調(diào)通整個 Pulsar 發(fā)送消息的流程,那么這里面肯定要涉及 Pulsar client 和 Pulsar broker 的交互,而 broker 是通過命令行啟動的,我如何調(diào)試 broker 里面的代碼呢?

我們可以觀察一下,bin/pulsar這個文件其實就是個 shell 腳本,可以找到這樣一段代碼:

elif [ $COMMAND == "standalone" ]; then
    PULSAR_LOG_FILE=${PULSAR_LOG_FILE:-"pulsar-standalone.log"}
    exec $JAVA $LOG4J2_SHUTDOWN_HOOK_DISABLED $OPTS ${ZK_OPTS} -Dpulsar.log.file=$PULSAR_LOG_FILE -Dpulsar.config.file=$PULSAR_STANDALONE_CONF org.apache.pulsar.PulsarStandaloneStarter $@

standalone命令其實就是運行java命令,輸入一大堆參數(shù),加載了一堆 jar 包,最終啟動了PulsarStandaloneStarter這個類,所以我們可以使用 JVM 遠程調(diào)試功能 。

IDE 就給我們提供了 Remote JVM Debug 功能:

圖片

我新建一個遠程調(diào)試,參數(shù)填默認的就行,這里 IDE 給我們自動生成了一段 JVM 參數(shù):

圖片

我們把這段 JVM 參數(shù)復制,把其中的suspend=n改成suspend=y,然后修改bin/pulsar文件,把這段參數(shù)添加到standalone模式的啟動參數(shù)中:

elif [ $COMMAND == "standalone" ]; then
    # 添加調(diào)試參數(shù),注意 suspend=y
    OPTS="${OPTS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"

    PULSAR_LOG_FILE=${PULSAR_LOG_FILE:-"pulsar-standalone.log"}
    exec $JAVA $LOG4J2_SHUTDOWN_HOOK_DISABLED $OPTS ${ZK_OPTS} -Dpulsar.log.file=$PULSAR_LOG_FILE -Dpulsar.config.file=$PULSAR_STANDALONE_CONF org.apache.pulsar.PulsarStandaloneStarter $@

這樣,我們本地命令行再執(zhí)行執(zhí)行bin/pulsar standalone時就會掛起:

$ bin/pulsar standalone --num-bookies 3
Listening for transport dt_socket at address: 5005

此時,你在 IDE 里可以給代碼隨意打斷點,點擊 debug 按鈕后 broker 才會啟動,走到斷點處將暫停,我們可以在 IDE 中查看變量、堆棧等信息。

這樣我們就能在 IDE 中同時調(diào)試 client 端和 broker 端的代碼了。

但是需要注意的是, 進行遠程調(diào)試的源代碼必須和命令行啟動的 broker 一致 ,否則會導致調(diào)試時行數(shù)對不上的問題。

如果出現(xiàn)源碼對不上的情況,可以在 pulsar 項目的根目錄用 maven 重新編譯當前的源碼:

$ mvn package -DskipTests -Dlicense.skip=true

編譯好的二進制包在distribution/server/target中,我們在新的包中的bin/pulsar腳本添加遠程 debug 的參數(shù),然后再次啟動即可順利調(diào)試。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 源碼
    +關注

    關注

    8

    文章

    630

    瀏覽量

    29074
  • 開源項目
    +關注

    關注

    0

    文章

    36

    瀏覽量

    7155
收藏 人收藏

    評論

    相關推薦

    Matepad pro12.2 已上市半個月,但是還沒有在開源網(wǎng)站看到該項目開源信息,違背開源精神

    任何該項目開源計劃,違背開源精神 按照開源社區(qū) licsence和公共庫開源licsence要求,對應的
    發(fā)表于 08-27 17:25

    機友分享 | 導入機智云Android開源項目的正確姿勢

    以下文章來源于小雨編程 ,作者小雨tt“使用機智云AIoT平臺支持項目自生成APP源碼,即可輕松解決Android開源項目啦,”開發(fā)者下載源碼
    發(fā)表于 09-28 10:58

    下載編譯源碼的要點和搭建源碼閱讀環(huán)境的方法

    下載編譯源碼的要點和搭建源碼閱讀環(huán)境的方法。下載編譯源碼,一方面是為了搭建源碼閱讀環(huán)境,另一方面
    發(fā)表于 01-10 06:49

    STM32項目開發(fā)中超級實用技巧分享

    STM32項目開發(fā)中超級實用技巧一. 利用軟啟動打補丁二. 優(yōu)化等級盡量選擇不優(yōu)化三. 合理利用開關總中斷所有的熱愛都要不遺余力,真正喜歡它便給它更高的優(yōu)先級,和更多的時間吧!關于STM32其它
    發(fā)表于 01-21 06:22

    2018 年 2 月份 GitHub 最熱門的開源項目

    2 月份 GitHub 最熱門的開源項目又出爐了,又有哪些新的項目擠進熱門榜單了呢,一起來看看。
    的頭像 發(fā)表于 03-23 08:53 ?4612次閱讀

    基于鴻蒙系統(tǒng)開源項目OpenHarmony源碼靜態(tài)分析

    開發(fā)者宣布了鴻蒙2.0系統(tǒng)開源,源碼托管在國內(nèi)源碼托管平臺碼云:https://openharmony.gitee.com/ 我也第一時間從碼云下載了鴻蒙系統(tǒng)的源代碼,并進行了編譯和
    的頭像 發(fā)表于 10-16 10:51 ?9379次閱讀
    基于鴻蒙系統(tǒng)<b class='flag-5'>開源</b><b class='flag-5'>項目</b>OpenHarmony<b class='flag-5'>源碼</b>靜態(tài)分析

    分享一個超級實用的源碼閱讀小技巧

    工欲善其事必先利其器; 我發(fā)現(xiàn)函數(shù)調(diào)用圖可以讓我們更加直觀地了解到源碼函數(shù)直接的調(diào)用和層次關系,提高閱讀源碼的效率 。 1 前言 看源碼的時候,心血來潮想弄一下函數(shù)之前的調(diào)用關系,想起
    的頭像 發(fā)表于 05-29 11:50 ?1977次閱讀
    分享一個超級實用的<b class='flag-5'>源碼</b><b class='flag-5'>閱讀</b>小技巧

    模擬閱讀開源分享

    電子發(fā)燒友網(wǎng)站提供《模擬閱讀開源分享.zip》資料免費下載
    發(fā)表于 11-14 11:21 ?0次下載
    模擬<b class='flag-5'>閱讀</b>器<b class='flag-5'>開源</b>分享

    矩陣顯示器的新聞閱讀開源項目

    電子發(fā)燒友網(wǎng)站提供《矩陣顯示器的新聞閱讀開源項目.zip》資料免費下載
    發(fā)表于 02-08 10:46 ?0次下載
    矩陣顯示器<b class='flag-5'>上</b>的新聞<b class='flag-5'>閱讀</b>器<b class='flag-5'>開源</b><b class='flag-5'>項目</b>

    閱讀開源項目源碼實用技巧(下)

    這句話其實是高效 debug 的關鍵。初看源碼時「猜」是很重要且很有效的手段,結合 IDE 的搜索功能,能夠幫我們快速定位關鍵代碼。
    的頭像 發(fā)表于 04-12 11:37 ?671次閱讀
    <b class='flag-5'>閱讀</b><b class='flag-5'>開源</b><b class='flag-5'>項目</b><b class='flag-5'>源碼</b>的<b class='flag-5'>實用技巧</b>(下)

    Java算法大全源碼開源源碼

    Java算法大全源碼開源源碼
    發(fā)表于 06-07 14:58 ?1次下載

    Haiku eInk閱讀開源分享

    電子發(fā)燒友網(wǎng)站提供《Haiku eInk閱讀開源分享.zip》資料免費下載
    發(fā)表于 06-15 14:45 ?0次下載
    Haiku eInk<b class='flag-5'>閱讀</b>器<b class='flag-5'>開源</b>分享

    Raymond Roussel閱讀開源分享

    電子發(fā)燒友網(wǎng)站提供《Raymond Roussel閱讀開源分享.zip》資料免費下載
    發(fā)表于 06-15 11:25 ?0次下載
    Raymond Roussel<b class='flag-5'>閱讀</b>機<b class='flag-5'>開源</b>分享

    如何去閱讀源碼,我總結了18條心法

    在一個優(yōu)秀的開源項目中,設計模式處處存在,所以在你開始閱讀源碼之前最好先了解一下常見的一些設計模式。當你了解了一些設計模式以后,在源碼中遇到
    的頭像 發(fā)表于 07-17 16:00 ?718次閱讀
    如何去<b class='flag-5'>閱讀</b><b class='flag-5'>源碼</b>,我總結了18條心法

    浙大博導開源飛控planner源碼

    浙大博導開源飛控planner源碼
    發(fā)表于 06-12 11:43 ?2次下載