為什么 Spring Boot 2.3.0 放棄 Maven 轉(zhuǎn)投 Gradle ?
在 2.3.0 中對 Spring Boot 進(jìn)行了相當(dāng)重大的更改,這是使用 Gradle 而非 Maven 構(gòu)建的項(xiàng)目的第一個(gè)版本。
Spring 的每個(gè)項(xiàng)目都獨(dú)立的項(xiàng)目組在開發(fā)運(yùn)營,在用戶最常使用的白盒部分(例如 API 設(shè)計(jì))保持一致性,對于用戶不可見的黑盒部分,各個(gè)項(xiàng)目組選擇自己適合工具沒有統(tǒng)一的約定。
例如: 項(xiàng)目構(gòu)建工具。Spring Framework 自 2012 年的 3.2.0 起就使用 Gradle 構(gòu)建,而一年后開始使用 Spring Boot,此后不久又開始使用 Spring Cloud,兩者都基于 Maven。
項(xiàng)目 | 構(gòu)建工具 |
---|---|
Spring Framework | Gradle |
Spring Boot | Maven |
Spring Cloud | Maven |
為什么要切換
Spring Boot 團(tuán)隊(duì)考慮由 Maven 切換到 Gradle 的主要原因?yàn)榱藴p少構(gòu)建項(xiàng)目所需的時(shí)間。在開發(fā)和測試過程中,等待構(gòu)建完成所花費(fèi)的時(shí)間增加了修復(fù)錯(cuò)誤和實(shí)現(xiàn)新功能所花費(fèi)的時(shí)間。
為了解決這個(gè)問題,團(tuán)隊(duì)曾嘗試?yán)?Maven 對并行構(gòu)建的支持。由于 Spring Boot 構(gòu)建的復(fù)雜性,特別是對 Invoker 插件的使用,嘗試失敗。通過將構(gòu)建分為四個(gè)部分來解決 CI 問題。首先構(gòu)建項(xiàng)目的主要核心,然后并行構(gòu)建三個(gè)獨(dú)立的部分。但 CI 的構(gòu)建仍需要一個(gè)小時(shí)或更長時(shí)間。此外,由于針對的是模塊化 CI 構(gòu)建,因此并沒有使得開發(fā)人員本地構(gòu)建效率有所改變。
Spring Boot 團(tuán)隊(duì)在其他利用 Gradle 作為構(gòu)建工具的 Spring 項(xiàng)目中看到了 Gradle 的增量和并行構(gòu)建以及在第三方項(xiàng)目中看到了 Gradle 的構(gòu)建緩存的好處。希望通過使用 Gradle 為 Spring Boot 構(gòu)建獲得類似的好處。
Gradle 具有非常靈活的構(gòu)建模型,并且可以定義每個(gè)任務(wù)的輸入和輸出及其相互依賴性。這種構(gòu)建模型的好處是,它允許任務(wù)并行運(yùn)行,同時(shí)也可以增量、緩存或完全跳過。換句話說,Gradle 可以最小化的執(zhí)行必要的 CI 任務(wù)。雖然可以使用了 Gradle Enterprise 的 Maven 支持,我們也可以享受構(gòu)建緩存和跳過的好處。但是要充分享受這四個(gè)方面的好處,必須嘗試切換到 Gradle。
如何切換
Gradle 配置過于靈活,導(dǎo)致它的構(gòu)建比基于 Maven 構(gòu)建更難以維護(hù)和理解。例如: 同一個(gè)構(gòu)建結(jié)果,可以通過不同的配置實(shí)現(xiàn)。如果切換到 Gradle,需要避免這種情況。從目前發(fā)布的四個(gè) Spring Boot 2.3 里程碑版本,在核心團(tuán)隊(duì)或貢獻(xiàn)者中,還沒有發(fā)現(xiàn)任何重大的構(gòu)建問題。
- Spring Boot 關(guān)鍵功能是約定優(yōu)于配置,將這種方法應(yīng)用于構(gòu)建。避免在 build.gradle 文件中包含命令式邏輯,編寫了幾個(gè)可以在項(xiàng)目的中找到的小插件 buildSrc。。
雖然現(xiàn)有 Gradle 生態(tài)系統(tǒng)對 Spring Boot 構(gòu)建幾乎空白,需要從頭通過編寫很多通用的 gradle 插件來應(yīng)用到 Spring Boot,但遷移到 Gradle 的提交從代碼庫中刪除了近 9500 行。
切換結(jié)果
就減少項(xiàng)目構(gòu)建時(shí)間而言,將構(gòu)建遷移到 Gradle 無疑是成功的。如上所述,在 CI 和開發(fā)人員機(jī)器上,基于 Maven 的完整構(gòu)建都需要一個(gè)小時(shí)或更長時(shí)間。而基于 Gradle 的平均成功構(gòu)建時(shí)間為 9 分 22 秒,如以下截圖所示:
如果對構(gòu)建性能的更多細(xì)節(jié)感興趣,可以在 Spring Boot 的公共Gradle Enterprise實(shí)例上獲得更多數(shù)據(jù)。
除了提高性能外,對其他功能進(jìn)行探索。例如,一段時(shí)間以來,進(jìn)行許多不穩(wěn)定的測試。由于這些原因,構(gòu)建失敗的次數(shù)比預(yù)期要多,可以在 Tests 儀表板中看到這一點(diǎn)。使用 Gradle 分片測試來替代 CI 的通用測試方案,并幫組我們了解是否已成功解決問題。
結(jié)論
CI 構(gòu)建現(xiàn)在平均大約需要 20 分鐘,比以前快 3-4 倍。
本地構(gòu)建平均需要 2 分鐘 30 秒,比以前快 20-30 倍。