Spring/Spring Boot編譯工具從Maven遷移到了Gradle
如果您正在考慮從 Maven 遷移到 Gradle,我希望了解更多有關(guān) Spring Boot 團(tuán)隊的經(jīng)驗是有用的。 如果你是一個快樂的Maven 用戶,請繼續(xù)使用和支持適合你的工具。
原文地址:https://spring.io/blog/2020/06/08/migrating-spring-boot-s-build-to-gradle
我們在 2.3.0.M1 中對 Spring Boot 進(jìn)行了相當(dāng)大的改變。 這是使用 Gradle 而不是 Maven 構(gòu)建的項目的第一個版本。 關(guān)于遷移的 Twitter 上的帖子 有很多人問我們?yōu)槭裁辞袚Q以及我們看到的好處(如果有的話)。 這篇博文旨在回答這些問題。
Spring 產(chǎn)品套件中的每個項目都以相當(dāng)自主的方式運行。 我們力求在用戶最容易看到的地方保持一致性--例如 API 設(shè)計,但選擇最能滿足項目需求的工具就不太明顯。 一個例子是構(gòu)建系統(tǒng)。 對構(gòu)建系統(tǒng)的改變會影響那些為項目做出貢獻(xiàn)的人,但如果我們做對了,它對用戶是沒有影響的。 這導(dǎo)致混合了基于 Maven 和 Gradle 的構(gòu)建。 例如,自 2012 年 3.2.0.M1 以來,Spring Framework就一直使用 Gradle 構(gòu)建;而 Spring Boot一年后誕生的,Spring Cloud也在此后不久開始,兩者當(dāng)時都使用基于 Maven 的構(gòu)建。 與 Spring Boot 不同的是,Spring Cloud目前沒有切換的計劃,因為Maven滿足他們的需求。 簡而言之,如果您從這篇博文中只得到一件事,那就是您應(yīng)該選擇最能滿足您項目需求的任何工具。
我們?yōu)槭裁匆袚Q?
Spring Boot 團(tuán)隊考慮切換到Gradle的主要原因是減少構(gòu)建項目所需的時間。 在進(jìn)行測試修改時,我們對反饋循環(huán)的長度感到沮喪。 等待構(gòu)建完成所花費的時間增加了修復(fù)錯誤和實現(xiàn)新功能所花費的時間。 我們在其他Spring 項目中看到了Gradle 的增量和并行構(gòu)建以及在第三方項目中的 Gradle 構(gòu)建緩存的好處。 我們希望我們可以在 Spring Boot 的構(gòu)建中獲得類似的好處。
我們過去曾嘗試?yán)?Maven 對并行構(gòu)建的支持。 由于 Spring Boot 構(gòu)建的復(fù)雜性,尤其是對 Invoker 插件的使用,我們的嘗試失敗了。 我們通過在CI(持續(xù)集成)上將構(gòu)建分成四個部分來解決這個問題。 該項目的主要核心是先構(gòu)建的,然后并行構(gòu)建三個獨立的部分。 這種安排雖然有所幫助,但CI構(gòu)建任務(wù)仍然需要一個小時或更長時間。 此外,由于拆分結(jié)構(gòu)是特定于 CI 構(gòu)建的,它并沒有使開發(fā)人員的本地構(gòu)建更快。
Gradle 有一個構(gòu)建結(jié)構(gòu)的廣泛模型,了解每個任務(wù)的輸入和輸出及其相互依賴關(guān)系。 這種建模的承諾是它允許任務(wù)并行運行,同時也可以增量、緩存或完全避免。 換句話說,Gradle 旨在最大限度地減少構(gòu)建任何給定更改所需的工作量,并行執(zhí)行必要的工作。 如果我們堅持并廣泛重組 Spring Boot 的構(gòu)建,那么使用 Maven 并行構(gòu)建可能是可行的。 而且,如果我們使用 Gradle Enterprise 的Maven支持,我們也可以享受構(gòu)建緩存和避免的好處。 然而,為了充分享受這四個方面的好處,我們覺得我們必須嘗試切換到 Gradle。
我們怎么切換?
我們看到的對 Gradle 的一種批評是,它導(dǎo)致構(gòu)建比基于 Maven 的同類產(chǎn)品更難維護(hù)和理解。 Gradle的靈活性允許以微妙不同的方式完成任務(wù),即使是在同一構(gòu)建中的模塊之間也是如此。 如果要成功切換,我們需要避免這種情況發(fā)生。 我們已經(jīng)發(fā)布了四個Spring Boot 2.3 里程碑(候選版本和 Gradle 的最終版本),看起來已經(jīng)成功了。 核心團(tuán)隊或任何其他貢獻(xiàn)者都沒有看到任何重大的構(gòu)建問題。
Spring Boot 的一個關(guān)鍵特性是“約定優(yōu)于配置”,我們也將這種方法應(yīng)用于構(gòu)建。遵循“ 避免在 build.gradle 文件中包含命令式邏輯 ”的建議,我們編寫了幾個可以找到的小插件在項目的 [buildSrc](https://github.com/spring-projects/spring-boot/tree/d4c7315369e7e9dce6eb1c77e5f23d1e670247c8/buildSrc)中。例如我們有一個starter plugin 應(yīng)用于每個 Spring Boot 啟動模塊,確保它們都被一致地配置、構(gòu)建和發(fā)布。我們還有一個約定插件對正在應(yīng)用的其他插件做出反應(yīng),并配置諸如源代碼編碼、JUnit 平臺的使用以及使用“-parameters”編譯等內(nèi)容。
這種方法導(dǎo)致 build.gradle 文件幾乎完全是聲明性的。 盡管我們編寫了許多插件來應(yīng)用我們的約定并填補Gradle 生態(tài)系統(tǒng)中的空白, 但遷移到 Gradle 的提交 卻從代碼庫中刪除了近 9500 行。
切換有好處嗎?
在減少項目的構(gòu)建時間方面,將構(gòu)建遷移到 Gradle 無疑是成功的。 如上所述,在 CI 和開發(fā)人員自己的機(jī)器上,一個完整的基于 Maven 的構(gòu)建需要一個小時或更長時間。 在過去的四個星期里,使用 Gradle平均成功構(gòu)建時間為 9 分 22 秒,如下面的屏幕截圖所示:
我們從 JDK 8 CI 構(gòu)建發(fā)布快照。 專注于那些,它在過去 4 周內(nèi)成功了 183 次 與 平均構(gòu)建 時間 19 分 37 秒。 查看成功的本地構(gòu)建,我們可以看到:
過去 4 周內(nèi)成功構(gòu)建了 273 個
平均構(gòu)建時間為 2 分 30 秒
Gradle 吸引我們的另一個好處是 我很享受 在為 Testcontainers 做貢獻(xiàn)時的體驗。 我們希望 Spring Boot 的貢獻(xiàn)者能夠盡快克隆和構(gòu)建項目。 感謝遠(yuǎn)程構(gòu)建緩存,可以 3 分鐘內(nèi)構(gòu)建完成,這包括下載大量依賴項所花費的時間。
如果您對構(gòu)建性能的更多細(xì)節(jié)感興趣,可以在我們的公共 Gradle Enterprise 實例 上獲得更多數(shù)據(jù)。
除了性能改進(jìn)之外,我們還開始研究其他一些可用的數(shù)據(jù)。例如,我們已經(jīng)意識到我們有一些不穩(wěn)定的測試一段時間了。由于它們,構(gòu)建失敗的頻率超出了我們的預(yù)期,我們現(xiàn)在可以在 Tests dashboard中看到這一點。我們已經(jīng)開始使用 Gradle 的易碎測試緩解來識別 CI 上發(fā)生的任何易碎測試幫助我們了解我們是否已成功解決或解決問題。
結(jié)論
我們對遷移的進(jìn)展以及我們所看到的構(gòu)建時間的減少感到非常滿意。 CI 構(gòu)建現(xiàn)在平均需要大約 20 分鐘,比以前快 3-4 倍。 本地構(gòu)建平均需要 2 分 30 秒,比以前快 20-30 倍。
我想借此機(jī)會感謝 Gradle 團(tuán)隊在遷移過程中提供的幫助,并慷慨地為我們提供了 Gradle Enterprise 許可證以用于我們的開源項目。 我們已經(jīng)將它與 Spring Framework、Spring Security 和 Spring Boot 一起使用,其他團(tuán)隊計劃開始將它用于基于 Gradle 和 Maven 的構(gòu)建。
我還要感謝我們正在使用的各種第三方插件的維護(hù)者。 他們提出了建議的更改并合并了拉取請求,以改進(jìn)對增量構(gòu)建和緩存的支持。 沒有它們,我們將無法實現(xiàn)我們所看到的構(gòu)建時間的減少。
如果您正在考慮從 Maven 遷移到 Gradle,我希望了解更多有關(guān) Spring Boot 團(tuán)隊的經(jīng)驗是有用的。 如果你是一個快樂的 Maven 用戶,請繼續(xù)使用和支持適合你的工具。
文章出自:??愛科學(xué)的衛(wèi)斯理??,如有轉(zhuǎn)載本文請聯(lián)系愛科學(xué)的衛(wèi)斯理今日頭條號。