將 Spring Boot 的建置遷移至 Gradle

工程 | Andy Wilkinson | 2020年6月08日 | ...

我們在 Spring Boot 2.3.0.M1 中進行了一項相當重大的變更。 這是該專案第一個使用 Gradle 而不是 Maven 建置的版本。 Twitter 上的主題 關於遷移,許多人詢問我們為什麼要切換,以及我們看到了哪些好處(如果有的話)。 這篇部落格文章旨在回答這些問題。

Spring 系列中的每個專案都以相當自主的方式運行。 我們努力在使用者最常看到的地方保持一致性——例如,API 設計——但對於不太明顯的事情,則選擇最能滿足專案需求的工具。 其中一個例子是建置系統。 建置系統的變更會影響貢獻者,但如果我們做得對,它對使用者沒有影響。 這導致了基於 Maven 和 Gradle 的混合建置。 例如,Spring Framework 自 2012 年的 3.2.0.M1 版本以來一直使用 Gradle 建置,而 Spring Boot 則在一年後開始,Spring Cloud 緊隨其後,兩者都使用基於 Maven 的建置。 與 Spring Boot 不同,Spring Cloud 沒有切換的計畫,因為 Maven 繼續滿足他們的需求。 簡而言之,如果您只想從這篇部落格文章中學習一件事,那就是您應該選擇最能滿足您專案需求的工具。

我們為什麼要切換?

Spring Boot 團隊考慮切換到 Gradle 的主要原因是減少建置專案所需的時間。 我們對於進行和測試變更時的回饋迴圈長度感到沮喪。 花在等待建置完成的時間增加了修復錯誤和實作新功能的時間。 我們已經在其他 Spring 專案中看到了 Gradle 的增量和並行建置的好處,以及 第三方專案中 Gradle 的建置快取 的好處。 我們希望我們可以在 Spring Boot 的建置中獲得類似的好處。

我們過去曾嘗試利用 Maven 對並行建置的支援。 由於 Spring Boot 建置的複雜性,尤其是它對 Invoker Plugin 的使用,我們的嘗試失敗了。 我們通過將建置分成四個部分來解決 CI 上的問題。 專案的主要核心首先建置,然後三個獨立的部分並行建置。 這種安排有所幫助,但 CI 建置仍然需要一個小時或更長時間。 此外,由於拆分結構特定於 CI 建置,因此它並沒有使開發人員的本機建置更快。

Gradle 具有廣泛的建置結構模型,了解每個任務的輸入和輸出及其相互依賴關係。 這種建模的承諾是,它允許任務並行運行,同時也是增量的、快取的或完全避免的。 換句話說,Gradle 旨在最大限度地減少建置任何給定變更所需的工作量,並並行執行必要的工作。 如果我們堅持並廣泛地重組 Spring Boot 的建置,則可以使用 Maven 並行建置。 而且,如果我們使用 Gradle Enterprise 的 Maven 支援,我們也可以享受建置快取和避免的好處。 但是,為了充分享受所有四個方面的好處,我們認為我們必須嘗試切換到 Gradle。

我們是如何切換的?

我們看到的對 Gradle 的一種批評是,它導致建置比基於 Maven 的等效建置更難以維護和理解。 Gradle 的靈活性允許以略微不同的方式完成事情,即使在同一個建置中的模組之間也是如此。 如果切換要成功,我們需要避免這種情況。 在使用 Gradle 發佈了四個 Spring Boot 2.3 里程碑、它的候選版本和最終版本之後,看起來我們已經成功了。 我們沒有在核心團隊或任何其他貢獻者那裡看到任何主要的建置問題。

Spring Boot 的一個關鍵特性是約定優於配置,我們也將這種方法應用於建置。 遵循 避免在 build.gradle 檔案中使用命令式邏輯 的建議,我們編寫了幾個可以在專案的 buildSrc 中找到的小型外掛程式。 例如,我們有一個 starter 外掛程式,它應用於每個 Spring Boot starter 模組,確保它們都以一致的方式進行配置、建置和發佈。 我們還有一個 conventions 外掛程式,它對應用程式的其他外掛程式做出反應,並配置諸如源代碼編碼、JUnit Platform 的使用以及使用 -parameters 進行編譯之類的事情。

這種方法導致 build.gradle 檔案幾乎完全是宣告式的。 即使我們編寫了許多外掛程式來應用我們的約定並填補 Gradle 生態系統中的空白,遷移到 Gradle 的提交 從代碼庫中刪除了近 9500 行代碼。

切換是否有益?

就減少專案的建置時間而言,將建置遷移到 Gradle 無疑是成功的。 如上所述,基於 Maven 的完整建置在 CI 和開發人員自己的機器上都需要一個小時或更長時間。 在過去的四個星期中,使用 Gradle 的平均成功建置時間為 9 分 22 秒,如下面的螢幕截圖所示

我們從我們的 JDK 8 CI 建置發佈快照。 關注這些,在過去的 4 週內成功了 183 次平均建置時間為 19 分 37 秒。 看看成功的本機建置,我們可以發現 在過去的 4 週內有 273 次成功的建置平均建置時間為 2 分 30 秒

另一個吸引我們使用 Gradle 的好處是 我貢獻 Testcontainers 時所享受的體驗。 我們還希望 Spring Boot 的貢獻者能夠儘快地克隆和建置該專案。 感謝遠端建置快取,一個乾淨的簽出可以在 3 分鐘內建置完成。 這包括下載大量依賴項所花費的時間。

如果您對建置的效能有更多詳細資訊感興趣,我們公開的 Gradle Enterprise 實例 上提供了更多資料。

除了效能改進之外,我們還開始研究一些其他可用資料。 例如,我們已經注意到一段時間,我們有很多不穩定的測試。 由於這些測試,建置失敗的頻率比我們希望的要高,現在我們可以 測試儀表板 中看到反映出來的現象。 我們已經開始使用 Gradle 的不穩定測試緩解措施來識別 CI 上發生的任何不穩定測試,並幫助我們了解我們是否已成功解決或繞過這些問題。

結論

我們對遷移的進展以及我們所看到的建置時間的減少感到非常滿意。 CI 建置現在平均需要大約 20 分鐘,比以前快 3-4 倍。 本機建置平均需要 2 分 30 秒,比以前快 20-30 倍。

我想藉此機會感謝 Gradle 團隊在遷移過程中提供的幫助,並感謝他們慷慨地為我們提供了 Gradle Enterprise 許可證,以便與我們的開源專案一起使用。 我們已經將它用於 Spring Framework、Spring Security 和 Spring Boot,其他團隊計畫開始將它用於他們基於 Gradle 和 Maven 的建置。

我還要感謝我們正在使用的各種第三方外掛程式的維護者。 他們提出了建議的變更並合併了提取請求,以改進對增量建置和快取的支援。 沒有他們,我們將無法實現我們所看到的建置時間減少。

如果您正在考慮從 Maven 遷移到 Gradle,我希望更多地了解 Spring Boot 團隊的經驗會很有用。 如果您是一位快樂的 Maven 使用者,請繼續使用和支援對您來說運作良好的工具。

取得 Spring 電子報

隨時掌握 Spring 電子報的最新資訊

訂閱

領先一步

VMware 提供培訓和認證,加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部