1. 程式人生 > >如何參與一個頂級開源專案

如何參與一個頂級開源專案

前言

最近個人事情比較多(搬家、換工作、短暫休息)所以一直也沒有顧得上部落格更新,恰好最近收到一封郵件提醒了我。

也是時候寫一篇文章來聊聊參與開源專案的事(最近也確實進入了筆荒期)。

ps:第一次收到這樣的中秋節禮物,加上 Dubbo 社群的活躍及阿里的重視度,還在做 PRC 或微服務技術選型的朋友可以考慮 Dubbo

參與開源

現在具體來聊聊參與開源的事;

日常幾乎所有的開發者都會享受到開源專案所帶來的便利甚至是收益,受限於環境早在十幾年前甚至幾年前開源活動一直都是有國外開發者主導。

但這幾年國內網際網路公司逐漸國際化擴大影響力也很大程度的提高了我們的開發水平,以 BAT 為首出現了許多優秀的開源專案。

現在甚至參與開源專案還能另闢蹊徑的拿到大廠 offer,所以其實不少朋友都想參與其中,可能這事給人的第一感覺就不太容易,所以現在還卡在第一步。

具體步驟

以下是以我個人經驗總結的幾大步驟:

  • 發現問題或自薦 feature
  • fork 原始碼。
  • 本地開發、自測。
  • 發起 pull request
  • 等待社群 Code Review
  • 跟進社群意見調整程式碼。
  • 稽核通過,合併進 master 分支,完成本次貢獻。

下面我會結合最近一次參與 Dubbo 的流程來具體聊聊。

發現問題或自薦 feature

首先第一步自然要搞清楚自己本次貢獻的內容是什麼?通常都是解決某個問題或者是提交一個新的 feature

;前者相對起來更加容易一些。

當然這個問題可以是自己使用過程中發現的,也可以是 Issues 列表中待解決的問題。

以本次為例,就是我在使用過程中所發現的問題,也提交了相關 Issue 並寫了一篇文章記錄並解決了該問題:What?一個 Dubbo 服務啟動要兩個小時!

值得注意的是在提交 Issue 之前最好是先在 Issue 列表中通過關鍵字檢索下是否已經有相關問題,避免重複。

同時提交之後也許社群會進行跟進,被打上 invalid 標籤認為不是問題,或者是使用姿勢不對也是有可能的。

fork 原始碼,本地開發

當確定這是一個待修復的問題時就可以著手開發了。

首先第一步自然是將原始碼拷貝一份到自己倉庫中。

接著只需要 clone 自己倉庫中的原始碼到本地進行開發。

先回顧下我遇到的這個問題。

簡單來說就是啟動 Dubbo 服務非常緩慢,經過定位是 main 執行緒阻塞在了獲取本機 ip 處。

所以當時我提出的方案是:在獲取本機 ip 時加上超時時間,一旦超時便丟擲異常或者是再次重試,但起碼得有日誌方便使用者定位問題。

問題是主執行緒會一直阻塞在此處 InetAddress.getLocalHost().getHostAddress(),但又需要知道它阻塞了多久才好判斷是否超時。

所以只能再額外開啟一個執行緒,定時去檢測 main 執行緒是否已經完成任務了,以下便是我第一次 pr 的內容。


這次的重點不是討論這裡具體的技術細節,所以簡單說下步驟:

  • 額為聲明瞭大小為 1 的執行緒池。
  • 再聲明瞭一個 volatile 標誌用於判斷主執行緒是否有完成任務。
  • 聲明瞭一個 condition 用於新執行緒做等待。
  • 最後只需要執行這個執行緒用於判斷這個標誌即可。

如何自測

開發完成後下一步就是自測,由於這類專案是作為一個基礎包依賴於其他的專案才能執行的,所以通常我們還得新建一個專案來配合做全流程測試(單測除外)。

這裡我覺得還是有幾個小技巧值得注意。

第一個是版本號;因為在本地測試,所以需要使用 mvn clean install 將包安裝到本地才能在其他專案中依賴進去進行測試。

但由於我們從官方拉出來的程式碼版本都已經發布到了 maven 中央倉庫中(不管是 release 還是 snapshot),所以我們本地倉庫中肯定已經存在這幾個版本的 jar 包。

一旦我們執行 mvn clean install 將自己修改的程式碼安裝到本地時,大概率是會出問題的(也可能是我姿勢不對),這樣就會導致新建的專案中依賴不了自己新增的程式碼。

所以我通常的做法是修改版本號,這個版本號是從來沒有被官方釋出到中央倉庫中的,可以確保自己新增的程式碼會以一個全新版本安裝到本地,這樣我們再依賴這個版本進行測試即可。

不過再提交時得注意不要把這個版本號提交上去了。

發起 pull request

自測完成後便可發起 pull request 了,不要大意,這裡還得有一個地方需要注意,那就是程式碼換行符的問題。

一旦換行符與源倉庫的不一致時,git 會認為這次修改是刪除後重來的,這樣會給 code review 帶來巨大的麻煩。

就像這樣,明明我改動的行數並不多,但 git 確認為你是推翻了重來,導致稽核起來根本不知道你改了哪些地方。

最簡單的方法就是設定自己 git 的全域性配置,可以參考這裡。

# 提交時轉換為LF,檢出時轉換為CRLF
git config --global core.autocrlf true

# 提交時轉換為LF,檢出時不轉換
git config --global core.autocrlf input

# 提交檢出均不轉換
git config --global core.autocrlf false

確認沒問題後便可點選這裡發起 pull request,後面按照引導執行即可。

當然各個專案之間還會有自己定製的貢獻流程,最好就是檢視官方的貢獻指南。

http://dubbo.apache.org/en-us/docs/developers/contributor-guide/new-contributor-guide_dev.html

Code Review

pr 發起後便可等待社群稽核了。

在這過程中要充分和社群進行交流,有可能你的方案和社群的想法並不一致。

比如像我這次:



最終通過溝通加上自己後面的思考覺得還是社群的方案更加輕便合理一些,達成一致之後社群便將這次 pr 合併進 master 中。

其實整個過程我覺得最有意義的便是 code review 的過程,所有人都可以參與其中頭腦風暴,其中也不乏技術大牛,不知不覺便能學到不少東西。

類似案例

雖然我之前的方案沒有被採納,但類似的用法(一個執行緒監控其他執行緒)還是不少,正好在 Dubbo 中也有用到。

便是其中核心的服務呼叫,預設情況下對使用者來說這看起來是一個同步呼叫,也就是說消費方會等待 PRC 執行完畢後才會執行後續邏輯。

但其實在底層這就是一個 TCP 網路包的傳送過程,本身就是非同步的。

只是 Dubbo 在你不知道的情況下做了非同步轉同步,這樣看起來就像是一個同步方法。

如圖中的紅框部分,Dubbo 自身呼叫了 get() 方法用於同步獲取服務提供者的返回結果。

邏輯其實也挺簡單,和我上文的方案類似,只是這裡的 isDone() 函式返回的是是否已經拿到了服務提供者的返回值而已。

總結

本次總結了參與開源的具體步驟,其實也挺簡單;就如官方所說哪怕是提個 Issue,修改一個錯別字都算是參與,所以不要想的太難。

最後還簡單分析了 Dubbo 呼叫過程中的非同步轉同步的過程,掌握這些操作對自己平時開發也是很有幫助的。

你的點贊與分享是對我最大的支援