如何找到并快速上手一個(gè)開(kāi)源項(xiàng)目
如何找到自己感興趣的開(kāi)源項(xiàng)目
首先第一步先想清楚自己搞開(kāi)源的目的是什么:
- 參考社區(qū)大佬的代碼,提升技術(shù)
- 豐富個(gè)人履歷,提高面試通過(guò)率
更功利一點(diǎn)就是想成為某個(gè)項(xiàng)目的 Committer/PMC
- 單純喜歡分享,熱愛(ài)開(kāi)源,認(rèn)可開(kāi)源改變世界??。
我人為前面三種都是一個(gè)目的,提升自己獲得后續(xù)的好處;最后一種則是妥妥的純熱愛(ài)。
以我個(gè)人來(lái)說(shuō),我兩者都沾一點(diǎn);我相信大部分人都是前面三類的目的,到這里我可能要先澆點(diǎn)冷水。
往往一個(gè)開(kāi)源項(xiàng)目從你熟悉它開(kāi)始到提第一個(gè) PR 然后到合并中間經(jīng)歷的時(shí)間可能是大大超出你的預(yù)期的。
特別是越大型越專業(yè)的項(xiàng)目(我相信你也是想加入這類有一定知名度的項(xiàng)目)。
因?yàn)殚_(kāi)源社區(qū)大部分都是執(zhí)行異步溝通,與即時(shí)通訊的快速反饋不同,甚至還有不少 reviewer 處于不同的時(shí)區(qū)。
所以一開(kāi)始就想做好心理預(yù)期,不要指望著我給某個(gè)項(xiàng)目提交一個(gè)很牛逼的功能,然后他們快速 review 合并,然后給你 commit 權(quán)限。
而且有不少開(kāi)源項(xiàng)目是由某一個(gè)公司主導(dǎo)的,比如(Pulsar、Golang、Kafka),他們可能對(duì)于外部社區(qū)來(lái)的新手并不那么上心,一個(gè) PR 晾在那里幾個(gè)月沒(méi)人理都是很正常的。
所以我建議一開(kāi)始選擇的項(xiàng)目有以下幾個(gè)篩選標(biāo)準(zhǔn):
- 盡量是自己日常在用,熟悉的項(xiàng)目。
- 最近有在及時(shí)更新維護(hù)的項(xiàng)目。
- 對(duì)社區(qū)新人的接納程度是否足夠包容。
- 這點(diǎn)可以在 Github 里查找標(biāo)簽為 help want/contribution welcome 的 issue 或者是 PR。
- 查看這些 issue/ PR 最近的活躍時(shí)間,貢獻(xiàn)者是否為新人。
- 往往一個(gè)包容度較高的項(xiàng)目以上信息都是很活躍的。
- 項(xiàng)目主要維護(hù)者是否來(lái)著不同的公司,是否足夠活躍。
圖片
圖片
推薦幾個(gè)我認(rèn)為比較符合我剛才提到的條件的項(xiàng)目:
- https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/7195
- https://github.com/apache/pulsar-client-go/issues?q=is%3Aopen+label%3Atype%2Ffeature+sort%3Aupdated-desc
- https://github.com/apache/hertzbeat/
如何快速上手一個(gè)開(kāi)源項(xiàng)目
如果找到了自己想貢獻(xiàn)的項(xiàng)目,如果自己還不太熟悉的話,那就可以嘗試以下步驟來(lái)快速上手它。
單元測(cè)試
首先第一個(gè)就是單元測(cè)試,單元測(cè)試是一個(gè)非常不錯(cuò)的方式來(lái)上手一個(gè)新的開(kāi)源項(xiàng)目,但重點(diǎn)不是去看現(xiàn)有的單測(cè),而是自己去寫??。
寫過(guò)單元測(cè)試的小伙伴就知道,如果要達(dá)到 90% 以上的覆蓋率時(shí)需要對(duì)自己寫的每一行代碼都得了解,甚至在寫的過(guò)程中會(huì)發(fā)現(xiàn)部分代碼是不是沒(méi)有必要,從而再幫助自己梳理一遍業(yè)務(wù)。
所以寫單測(cè)確實(shí)是快速熟悉某個(gè)項(xiàng)目的方法,但這針對(duì)于一些邏輯簡(jiǎn)單的項(xiàng)目;對(duì)于一些業(yè)務(wù)復(fù)雜的項(xiàng)目建議還是快速跑通官方推薦一個(gè)功能。
以 Pulsar 為例
以 Apache Pulsar為例,那就先跑一個(gè)消息的生產(chǎn)者和消費(fèi)者 demo;跑通了之后再嘗試看看它客戶端已有的單測(cè)代碼,然后嘗試改一些斷言,此時(shí)就會(huì)發(fā)現(xiàn)預(yù)期值為什么會(huì)這么定義。https://github.com/apache/pulsar/blob/631b13ad23d7e48c6e82d38f97c23d129062cb7c/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/BrokerClientIntegrationTest.java#L1077
圖片
圖片
比如這里的一個(gè) consumer 取消訂閱兩次時(shí)候就會(huì)拋出異常,此時(shí)我們就可以根據(jù)異常的地方找到源碼里對(duì)連接狀態(tài)的判斷條件。
就可以得知:當(dāng)客戶端取消訂閱時(shí)會(huì)修改連接狀態(tài)。
HertzBeat
下面以 Apache HertzBeat為例來(lái)看看當(dāng)時(shí)我是如何貢獻(xiàn)單元測(cè)試的。
圖片
通過(guò)官方的架構(gòu)圖可以得知 HertzBeat 是通過(guò)一個(gè) collector 去直連目標(biāo)采集數(shù)據(jù)的。
比如通過(guò) Redis 的客戶端去獲取監(jiān)控?cái)?shù)據(jù),然后再存放到自己的時(shí)序數(shù)據(jù)庫(kù)中進(jìn)行展示。
所以這個(gè)采集的過(guò)程就是比較核心的邏輯,我們可以看看他的接口定義。
圖片
一共就三個(gè)接口,分別是:
- collect采集接口:在 Metrics 中定義了采集的目標(biāo)信息(地址、端口等)
- 采集完后的數(shù)據(jù)寫入到 Builder 供后續(xù)的寫入存儲(chǔ)
- preCheck:提前做一些參數(shù)校驗(yàn)
- supportProtocol:返回定義的協(xié)議類型,通過(guò)這個(gè)類型找到對(duì)應(yīng)采集器
圖片
然后就交由不同的實(shí)現(xiàn)類去采集不同的指標(biāo)。
這里我以 RedisCommonCollectImpl為例,主要的單測(cè)邏輯就是模擬 Redis 客戶端的返回?cái)?shù)據(jù),然后在 Collect 的代碼里查看不同的處理邏輯,其實(shí)就是要覆蓋各種分支以及異常的情況。
最后再斷言采集到的數(shù)據(jù)與預(yù)期是否匹配即可,貼一段核心邏輯:
圖片
至于應(yīng)該返回什么預(yù)期結(jié)果,有些 collector 可能會(huì)在代碼注釋里寫清楚,但這個(gè) Redis 沒(méi)有寫。
不過(guò)也有辦法,我們可以把代碼在本地跑起來(lái)之后進(jìn)入管理臺(tái)查看內(nèi)置的監(jiān)控模版。
圖片
這里是用于定義會(huì)監(jiān)控哪些字段的地方,這樣我們就可以在代碼預(yù)先生成好預(yù)期返回值了。
圖片
具體的單測(cè)代碼請(qǐng)看這里:https://github.com/apache/hertzbeat/blob/master/collector/src/test/java/org/apache/hertzbeat/collector/collect/redis/RedisClusterCollectImplTest.java#L46
總結(jié)
參與一個(gè)成熟社區(qū)的開(kāi)源有一點(diǎn)一定要記住,就是要仔細(xì)閱讀貢獻(xiàn)者文檔。
里面往往會(huì)寫清楚如何構(gòu)建代碼、代碼規(guī)范、提交規(guī)范等信息,這些都捋清楚后提交的 PR 才更容易被社區(qū)接受。
后面會(huì)繼續(xù)更新集成測(cè)試與 e2e 測(cè)試等內(nèi)容。