開源指南|如何從零開始參與 Apache 頂級開源專案?(二)

語言: CN / TW / HK

作者:蘇奕嘉|SelectDB 生態研發工程師

寫在開頭

上一篇文章 如何從零開始參與 Apache 頂級開源專案? 我們介紹了 Apache Doris 社群的工作機制、如何參與社群貢獻以及如何完成第一個 PR,更多是從大而全的角度來介紹參與開源專案的一些定式,希望能為新人開發者提供一個簡單的思路。

思路固然重要,而詳細的指引也是新人開發者真正參與開源的關鍵,在本篇文章中,我們將會為大家介紹以下內容:

  1. 參與 Apache Doris 開發至少需要掌握哪些技術棧

  2. Apache Doris 開發環境搭建

  3. 程式碼結構介紹以及程式碼改動

  4. 如何進行文件貢獻

  5. 如何提交一個合格的 PR

  6. 如何解決衝突以及 Rebase 程式碼

  7. ci 檢查失敗該如何處理

本文將通過以上內容為新人開發者提供一個詳盡的入門指引,希望有更多熱愛開源的小夥伴可以加入到 Apache Doris 社群中,無論是文件貢獻或程式碼開發,亦或是參與宣傳推廣和分享應用案例,都是社群非常歡迎的貢獻方式。那麼接下來我們將展開各項詳細說明。

第 0步:掌握技術棧

Apache Doris 的系統架構非常精簡,只有 Frontend(FE) 和 Backend(BE) 兩類程序,FE 節點主要負責使用者請求的接入、查詢解析規劃、元資料的管理以及節點管理相關工作,BE 節點主要負責資料儲存、查詢計劃的執行。

除此以外,Apache Doris 不依賴任何其他的元件,例如不依賴 HDFS 進行資料儲存、不依賴 Zookeeper 進行分散式管控,相對於 Druid、Clickhouse 之類的 OLAP 資料庫,Apache Doris 架構精簡的優勢極大的降低了運維壓力,同時,Doris 無論是在升級還是擴縮容方面都更加的便捷。

FE 由 Java 語言編寫, BE 出於效能考慮使用 C++ 語言實現, 開發 過程中 必備 技術棧 包括

  • FE:Java、Maven
  • BE:C++

第 1 步:Apache Doris 開發環境搭建

Apache Doris 主要程式碼語言為 Java 和 C++,我們分別就 FE 和 BE 的開發環境搭建進行說明。

FE 開發環境

FE 中的 Java 程式碼由 Maven 管理,推薦使用 IntelliJ IDEA 進行開發,

IntelliJ IDEA 的開發環境搭建可以參閱 官方文件 ,連結:

https://doris.apache.org/zh-CN/community/developer-guide/fe-idea-dev

在工程建立完成後,建議配置 IDEA 如下兩個功能,以方便通過程式碼格式檢查:

  • Editor -> Code Style -> Java 中配置 Imports Order。

  • Save Actions 設定儲存時自動格式化。建議在格式化選項中僅勾選 Optimize importsReformat only changed code ,以保證 Import 順序,同時避免未變更的程式碼被自動格式化。

BE 開發環境

BE 開發環境請參閱 官方文件 ,連結:

https://doris.apache.org/zh-CN/community/developer-guide/be-vscode-dev

BE 的程式碼自動格式化請參閱 官網文件 ,連結:

https://doris.apache.org/zh-CN/community/developer-guide/cpp-format-code

Apache Doris 使用 clang-format 進行程式碼格式化,並在 build-support 目錄下提供了封裝指令碼:

  • clang-format.sh.
  • 格式化 be/srcbe/test 目錄下的 C/C++ 程式碼。
  • check-format.sh.
  • 檢查 be/srcbe/test 目錄下的 C/C++ 程式碼格式,並將 diff 輸出,但不會修改檔案內容。

第 2 步:程式碼結構介紹及程式碼改動

程式碼結構介紹

我們將介紹 Apache Doris Master 分支為例的程式碼模組都有哪些,便於大家快速檢索。

master-``9a74ad1 為例,根目錄索引如下:

├── be                  // BE 程式碼目錄
├── bin                 // FE/BE 的啟停指令碼
├── build_plugin.sh     // FE 外掛編譯指令碼
├── build.sh            // Doris 編譯指令碼
├── build-support       // 編譯用輔助指令碼
├── CODE_OF_CONDUCT.md  // 貢獻者程式碼行為準則
├── conf                // FE/BE 的配置檔案
├── contrib             // 第三方貢獻程式碼,如 udf
├── CONTRIBUTING_CN.md  
├── CONTRIBUTING.md
├── DISCLAIMER
├── dist                // 許可證目錄
├── docker              // Doris 開發映象的 Dockerfile
├── docs                // 文件目錄
├── env.sh
├── extension           // 擴充套件功能程式碼,如 flink connector 等
├── fe                  // FE 程式碼目錄
├── fe_plugins          // FE 外掛目錄
├── fs_brokers          // Broker 程式碼目錄
├── gensrc              // thrift/protobuf 等程式碼生成目錄
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── regression-test     // 迴歸測試目錄
├── run-be-ut.sh        // BE 單元測試執行指令碼
├── run-fe-ut.sh        // FE 單元測試執行指令碼
├── run-tegression-test.sh
├── samples             // 示例程式碼目錄
├── thirdparty          // 第三方依賴庫目錄
├── tools               // 一些輔助工具
├── tsan_suppressions
├── ui                  // FE 前端程式碼目錄
└── webroot             // 一些靜態網頁相關程式碼


使用中經常涉及到的開發目錄有:

  1. FE 程式碼目錄:fe/
  2. BE 程式碼目錄:be/
  3. Thrift 等程式碼生成目錄:gensrc/
  4. 擴充套件功能程式碼目錄:extension/
  5. 迴歸測試目錄:regression-test/

FE

├── check
├── fe-common   // 一些 FE 模組的通用程式碼
├── fe-core     // FE 模組主程式碼
├── hive-udf    // hive-udf 模組程式碼
├── java-udf    // java-udf 模組程式碼
├── pom.xml
├── README
└── spark-dpp   // Spark Load 所依賴的 Spark 匯入程式程式碼


fe-core 目錄下是 FE 的程式碼核心模組。

├── main            
│   ├── cup         // 語法定義檔案
│   ├── java        // 主程式碼
│   ├── jflex       // 詞法定義檔案
│   ├── antlr4      // 詞法分析器
│   └── resources
└── test             // 單元測試
    ├── java
    └── resources


在主程式碼路徑下,也就是上述樹狀的 main/java/org/apache/doris/ 目錄下,有如下的主要程式碼部分:

├── alter         // 表結構變更操作相關的程式碼。包括表結構變更,物化檢視等。
├── analysis      // 包含所有SQL語法的java例項類
├── backup        // 備份恢復操作相關的程式碼
├── blockrule     // SQL 黑名單相關程式碼
├── catalog       // 包含元資料操作的主類和各種資料庫、表、分割槽的元資料例項類
├── clone         // 資料副本修復和均衡相關的程式碼
├── cluster       // 已廢棄
├── common        // 一些工具類和通用定義
├── consistency   // 資料一致性校驗相關的程式碼
├── deploy        // 部署相關程式碼
├── external      // Doris on Elasticsearch相關的程式碼
├── ha            // 元資料高可用相關的程式碼
├── http          // http v1 程式碼
├── httpv2        // http v2 程式碼(逐步替換v1)
├── journal       // 元資料日誌相關的程式碼
├── ldap          // LDAP 認證相關程式碼
├── load          // 匯入作業相關程式碼
├── master        // FE Master角色相關的操作程式碼,如元資料Checkpoint,BE任務彙報的處理等。
├── metric        // FE 監控指標相關的程式碼
├── monitor       // JVM 監控相關程式碼
├── mysql         // MySQL協議層相關程式碼
├── nereids       // 優化器相關程式碼
├── PaloFe.java   // Main函式入口
├── persist       // 元資料持久化相關的程式碼
├── planner       // 查詢優化器相關的程式碼
├── plugin        // Frontend端外掛管理相關程式碼
├── policy        // 儲存策略相關程式碼
├── qe            // 用於處理各類SQL請求相關的程式碼。如查詢請求的處理類、DDL請求的處理類等
├── resource      // 資源標籤相關的程式碼
├── rewrite       // 查詢優化器重寫規則相關的程式碼
├── rpc           // Frontend和Backend之間RPC協議相關的程式碼
├── service       // Frontend側各種伺服器端程式碼
├── statistics    // 統計資訊相關程式碼
├── system        // 叢集節點的例項類和叢集節點管理相關的程式碼
├── tablefunction // 表函式相關程式碼
├── task          // Frontend發往Backend的各類任務相關的程式碼
└── transaction   // 匯入事務相關程式碼


BE

├── CMakeLists.txt  // CMake 編譯檔案
├── src             // 主程式碼目錄
└── test            // 單元測試


其中,主要程式碼目錄包含如下內容:

├── agent                   // FE 下發的 agent task 相關處理類
├── common                  // 通用類
├── env                     // 檔案系統操作類
├── exec                    // 執行運算元相關程式碼
├── exprs                   // 表示式、函式計算相關程式碼
├── gen_cpp                 // 
├── geo                     // 地理位置函式相關程式碼
├── glibc-compatibility     // GLIBC 相容程式碼
├── gutil                   // Google gutil 相關程式碼
├── http                    // BE 端 http server 相關程式碼
├── io                      // 
├── olap                    // 儲存層程式碼
├── runtime                 // 查詢層執行時相關程式碼
├── service                 // BE 對外服務介面相關程式碼
├── tools                   // 輔助工具相關程式碼
├── udf                     // 使用者自定義函式相關程式碼
├── util                    // 一些工具類
└── vec                     // 


gensrc

├── Makefile
├── proto       // protobuf 定義檔案
├── script      // 一些輔助指令碼,包括函式定義程式碼生成模板等
└── thrift      // thrift 定義檔案


extension

├── DataX                   // DataX doriswriter 外掛
├── dbt-doris               // DBT 外掛
├── logstash                // logstash 匯入外掛
└── mysql_to_doris          // MySQL 匯入插入


regression-test

├── common         // 迴歸測試框架通用程式碼
├── conf           // 配置類檔案
├── data           // 測試結果集
├── framework
├── plugins        // 外掛目錄
├── script         // 指令碼目錄
└── suites         // 測試程式碼目錄


如果對以上某個模組感興趣,均可以通過目錄檢索對照完成快速定位。

程式碼改動

這裡的程式碼改動不僅指 Java / C++ / Python 等程式語言的改動,文件內容改動、程式碼註釋改動等,也都屬於程式碼改動範疇,所述程式碼改動均可以通過目錄檢索定位到對應的位置來修改。

舉例:

  • 文件修改,需要到 /docs 目錄下修改對應的 .md 檔案。
  • 程式碼修改,到指定目錄下修改相應的檔案內容。

第 3 步:參與文件貢獻

在 Apache Doris 官網目前的文件結構中,文件被分為歷史文件與 dev 文件。在開發過程如果發現文件勘誤,需要在不同倉庫目錄下對文件提交修改。

其中,歷史文件有 0.15 和 1.1 兩個版本號,文件版本號與 Apache Doris 核心版本保持一致,位於 https://github.com/apache/doris-website 倉庫中

Website 程式碼目錄結構可以參考連結:https://doris.apache.org/zh-CN/community/how-to-contribute/contribute-doc

dev 文件與當前 Master 版本一致,位於 https://github.com/apache/doris/tree/master/docs

  • 如果需要修改的文件只涉及當前 dev 版本,直接在 Master 上進行修改並提交 PR 。
  • 如果需要修改的文件同時出現在 dev 版本及歷史版本中,則需要分別在 doris-website 和 apache/doris 兩個程式碼倉庫提交 PR。

舉例說明:

1) 文件修改。 以下面文件示例,在 Apache Doris 官網中,我們發現有一篇文章的描述出現錯誤,需要刪除該內容。

首先在 apache/doris 程式碼倉庫的 master 分支中找到對應的該文件,中文文件在 docs/zh-CN/docs/data-table/data-partition.md ,找到需要刪除的語句描述進行刪除。

英文文件在 docs/en/docs/data-table/data-partition.md ,步驟如上,刪除對應英文描述。

需要注意的是:文件類的修正 定需要同時修改中文和英文 兩個 文件 修改後,分別建立 Pull Request 進行提交。

2) 提交 Blog 目前 Apache Doris 官網提供了 Blog 功能,歡迎所有人分享優質技術內容到官網 Blog 中。Blog 不區分文件版本,所有版本通用, 因此 只需要在 apache/doris-website 中提交一次 PR **** 無需在多個版本中重複提交。

中英文 Blog 處於不同的目錄下,英文部落格位於根目錄下的 Blog 中,連結 https://github.com/apache/doris-website/tree/master/blog。中文部落格目錄在 i18n/zh-CN/docusaurus-plugin-content-blog 。提交 Blog 時,只需要將中英部落格對應的 markdown 檔案分別置於兩個目錄下,需要注意的是,中英文部落格的檔名稱需要保持一致。

第 4 步:如何提交一個合格的PR

看到這一步,相信有很多小夥伴已經迫不及待要開始程式碼提交之路,先彆著急,還有一些問題需要解決。比如:如何快速找到想要改動或者擅長的程式碼模組呢?

接下來 介紹 如何提交程式碼到遠端 完成一個合格的 PR

嚴格來講,提交本地改動到 Remote 端的步驟是三步:

  1. add 檔案
  2. commit 暫存提交
  3. push 推送遠端

如果 使用的 是 Git 命令列工具,應執行以下的通用流程:

git add <file>
git commit -s -m "some description here"
git push origin feat-xxx


  1. add <file> :新增本次改動的檔案目錄,如果想新增所有改動檔案,不需要一一指定,使用 git add --all 即可。
  2. commit 暫存提交:將暫存提交內容和描述資訊到本地,-s 引數一定要新增,-m 引數後面是本次提交內容的描述資訊。
  3. push 推送遠端:是執行推送本地改動到遠端的動作, feat-xxx 代表要提交的分支,還有一些引數,如 -f 引數,作用在當 commits 記錄不滿意,仍需強制覆蓋遠端分支的引數,根據具體情況靈活調整。

如果使用的是 Git GUI 工具,如 IDE 的 Git 外掛,SourceTree、SmartGit、TorToiseGit等,根據相對應的功能模組按步驟操作即可。

以上面修改的文件提交為例,我們執行如下操作:

cd doris
git add docs/zh-CN/docs/data-table/data-partition.md
git add docs/en/docs/data-table/data-partition.md
git commit -s -m "Fixed incorrect description of column length limit in partition bucketing documentation."
git push origin docs-data-table


可以注意到, commit 描述都是用英文,鼓勵大家使用英文描述來提交 commit 以及 PR 。

當進行提交時如果提示輸入 GitHub 賬號名和密碼,輸入後又提示鑑權失敗,原因是未配置 SSH 免密機器,需要在賬戶 settings 中建立 token 來當做密碼,具體流程不再贅述。成功後提示如下:

提交後,我們回到個人 Gitgub 賬戶下 Fork 後的程式碼庫,發現有黃色提示框來提示有改動,我們可以建立一個 PR 來回歸上游程式碼庫,操作如下:

點選按鈕 Compare & pull request 建立一個 PR。

一個合格的 PR 內容,應該有三部分組成:

  1. 正確的分支指向,即你當前修正的分支提交到目標源倉庫分支,這裡我們是從 FreeOnePlus/doris/docs-data-table 分支迴歸合併到 apache/doris/master 分支來。
  2. 正確的標題名稱,不同的改動內容,需要配以不同的型別標題來進行劃分,如果不按如下的通用格式書寫,會導致 PR 合入失敗,格式應為:[<type>](<scope>) <subject> (#pr),比如文件標題應以 [docs] 開頭,如我們示例的這次改動,應該命名為: [docs](docs)Partition table document correction 或者 [docs]Partition table document correction。如果是 Bug 修復的程式碼改動,那應該以 [fix] 作為標題字首,(<scope>)一定要有,更多型別可以閱讀官方文件(https://doris.apache.org/zh-CN/community/how-to-contribute/commit-format-specification/)來了解。
  3. 詳略得當的修改內容說明,往往開源社群會預製一個模板,目標是清晰的描述修改內容,以便於 review 同學和其他同學能更快的瞭解你做的改動,按文件內容要求來填寫即可。參考如下:

合格的 PR 三部分完成後,即可點選右下角的 Create pull request 按鈕完成 PR 建立。提交 PR 成功後,跳轉至 PR 詳情頁,這時候需要注意 ci 檢查是不是全部能夠通過,假如失敗了,需要及時修復。

第 5 步:如何解決衝突

提交 PR 時發生程式碼衝突一般是由於多人編輯同一個檔案引起的,解決衝突主要通過以下步驟即可:

(1)切換至主分支

git checkout master


(2)同步遠端主分支至本地

git pull upstream master


(3)切換回剛才的分支(假設分支名為fix)

git checkout fix


(4)進行rebase

git rebase -i master


此時會彈出修改記錄的檔案,一般直接儲存即可。會提示哪些檔案出現了衝突,此時可開啟衝突檔案對衝突部分進行修改,將提示的所有衝突檔案的衝突都解決後,執行

git add .
git rebase --continue


依此往復,直至螢幕出現類似 rebase successful 字樣即可,此時您可以進行往提交PR的分支進行更新:

git push -f origin fix


第 6 步:ci 檢查如何處理和修改

如果 PR 沒有問題,通過 Reviewers 進行 Review 以後,很快會將 PR 合併進去,這樣 PR 的生命週期也就到此結束了,如果社群其他同學提出了疑問,他們或許會在 PR 底下的評論區提出自己的質疑,記得要及時響應。

如果程式碼改動沒有被合入,Reviewer 指出了問題所在,需要進一步修改時,無需重新走一遍流程建立一個新的 PR 進行改動,更無需從 Fork 倉庫開始。

只需要在本地繼續修改即可,修改成後將改動 commit & push 到遠端, PR 會自動追蹤和更新內容, Reviewers 進行二次 review 即可,修改後需要至少一個非作者的 Committer 給出 LGTM 或者 +1 後方可合併入。

Enjoy it again!

參與開源專案的方式是多種多樣的,無論是提交 Issue 或參與 PR Review,或是修改和完善文件,亦或是分享技術部落格和應用案例,都是參與開源貢獻的一種方式。

同時,有很多不起眼、但富有意義的工作希望得到更多開發者的幫助:

  • 在即將釋出的 1.2 版本中將會支援 Java UDF,歡迎參與編寫 Java UDF;
  • 在迴歸測試庫中有大量測試 Case ,大多需要編寫 SQL 指令碼來完成功能和效能測試的,非常歡迎根據自己的業務場景提供迴歸測試 Case 來幫助 Doris 發版更加穩定。
  • 還有諸如各種 build.sh、build_plugins.sh 、docker-compose.yaml 、dockerfile 等指令碼,等你來改進和新增。
  • 發現文件內有描述謬誤、解釋不清、示例錯誤、排版問題甚至錯別字和錯誤的標點符號,都可以提交 PR 參與到對 Apache Doris 的貢獻中來。

與此同時,Apache Doris 社群特別歡迎所有使用者根據自己的業務來書寫相應的最佳實踐文件,或者在使用過程中對某個功能或者某個模組的詳細使用文件,比如《 MySQL 資料遷移至 Doris 的最佳實踐》等。

綜上,貢獻 Apache Doris 所需要的技術棧並非一定是工程能力的技術棧,也可以在非程式碼貢獻層面做些力所能及的事情, 我們歡迎開源愛好者參與到社群中來。

「其他文章」