LinkedIn:用Gradle構建Java Play框架應用

在LinkedIn,咱們一直在評估最好的開發框架和工具來開發偉大的產品。11年的歷史中,咱們使用過不少前端web框架-如Grails、Frontier(LinkedIn內部的web框架),最近是:Play!咱們喜歡Play,並熱情地在公司內部推行起來。因而咱們用Play進行了整合和擴展。如今咱們正在評估哪一個構建系統(build system,下同)更好用。html

這篇文章介紹了用在Play中用Gradle來支持開發,及Gradle的目前狀態和它的初步特性的演化。咱們但願Play社區提供更多反饋以幫助Gradle類軟件的開發。可以給Sbt和Gradle開發Play應用將提供更多的自由度和多樣性。前端

背景:代碼的組織

在LinkedIn,咱們用代碼倉庫管理公共API和服務,每一個這種倉庫咱們給它取了個名叫 Multiproduct,每一個Multiproduct經過獨立的Ivy來組織,默認的名稱是com.linedin。LinkedIn的部分代碼已經開源了,如databusjava

用Multiproducts來組織代碼的結果是,它們都是多工程的構結構,每一個Multiproduct有10個或100個工程,同時每一個工程又有多個 構件(artifacts,下同)。git

在LinkedIn,咱們的Play應用在classpath路徑下有超過500個jar包,這意味着全依賴解析的話須要處理至少500個節點。但依賴解析重度依賴於衝突解決的規則(致使效率低)。咱們不在構件(如jar)層解析版本,而是在Multiproduct(或Ivy組織)層處理,這樣能夠保證同一個Multiproduct內所有構件版本是一致的。github

例如,工具類util Multiproduct,咱們有3個不一樣的模塊,com.linkedin.util:foo, com.linkedin.util:bar, com.linkedin.util:baz。每個模塊可能有一個或多個構件,通常的衝突解決辦法 可保證全部模塊只有一個版本,但不一樣模塊間的版本(本例中的"com.linkedin.tuil:foo", "com.linkedin.util:bar", and "com.linkedin.util, baz")仍可能不一樣。咱們自定義依賴處理器將確保同一個Multiproduct中的全部構件是同一個版本。web

使用SBT的擴展性挑戰

Play默認的構建工具是SBT,Play與SBT在技術上是解耦了,但底層仍有不少未分離。當咱們開始開發Play應用時,很快就遇到了SBT擴展性方面的挑戰,並且很依賴於Apache Ivy庫,某個應用的依賴解析須要5-10分鐘,一個框架工程呢,就要花30分鐘以上。apache

過去一年,LinkedIn跟Typesafe合做來提高SBT的擴展性,如今還在繼續,然而,同時,咱們感受到評估下其它的構建工具也是值得的。瀏覽器

Play與Gradle的整合

LinkedIn已經使用Gradle有3.5年了,處處都有gradle的影子,從小項目到單個Multi-product構建了近4000個工程,並且2015年的gradle還帶了許多激動人心的新特性。緩存


除了以上,咱們相信整合二者對雙方都頗有價值,跟Gradleware 一塊兒咱們開始研究若是讓它成爲現實。2015年上半年,咱們將注重整合的實現和測試,已經完成 3個里程碑 了。app

里程碑1:用Gradle來開發一個Play應用。

讓Gradle與Play的插上電,開發者能夠用gradle構建一個具備Play所有特性的應用。

特性包括:

  • 編譯Java和Scala源碼

  • 編譯路由

  • 編譯模板

  • 編譯資源/配置文件

  • 支持CoffeeScript, LESS/CSS, JavaScript

使用這個構建管道,Play應用能夠用 gradle run 或 gradle start 啓動,或用 gradle stage 或 gradle dist 來發布。

有了這個能力咱們就能夠全面的測試Play的構建系統的性能和可擴展性了。

提示:這個里程碑裏 持續模式(continuous mode) 和 熱加載(hot reload) 不支持。

里程碑2:持續模式 和 熱加載

開發應用時可以熱加載將是最使人愉快的Play特性。

自動化以前手工打包處理是一個偉大的主意,咱們熱切但願能加到gradle裏。里程碑2將介紹Gradle的「觀察者」模式,這跟SBT的持續模式(continuous mode)相同:gradle --watch run。

Play也能夠當瀏覽器刷新時自動從新構建,這是經過Play的BuildLink接口實現的,這個里程碑將包含這個特性。

里程碑3:變爲現實

若是你熟悉Play可能已經注意到了缺失了一個嚴重的特性:Scala的交互功能 REPL!別急....這是里程碑3的一部分,將容許你在控制檯與類(classes)進行交互。

還有文檔,跟Specs2 整合了, 還有Scala的代碼也優雅的集成了。爲了讓這些一塊兒啓動起,你須要一個適當的Gradle基礎平臺,就像你以前用activator同樣。

想了解更多?能夠參考這裏

初試 里程碑1

該里程碑的特性已經完成了,你能夠下載最新版本嘗試下。下載包裏有二進制文件、源代碼文件和例子工程。解壓縮後加「bin」路徑加到你的環境變量。

Play的例子在 「samples/play」 目錄。

基本的

基本例子 build.gradle 文件演示了Play插件聲明及倉庫需求配置,依賴塊展現了若是定義第3方類庫,'play' 配置提供了統和運行依賴,'playTest' 提供了測試時的依賴定義。

高級的

高級例子 build.gradle 展現了若是配置成 Play/Scala 版本。

Multiproduct:

這是標準的Gradle multiproject 構建配置,根目錄包含了Play主應用,3個子模塊在modules目錄下,admin和user子模塊在在各自文件夾裏,utile是一個java 類庫。settings.gradle 文件鏈接了3個子工程,主工程build.gradle 描述了3個子模塊各自的依賴。

你能夠嘗試執行如下任務:

  • gradle :assemble :構建 jar 和 assets

  • gradle :runPlayBinary : 構建和運行應用在開發者模式

  • gradle :check : 執行測試用例

  • gradle :stage : 構建和發佈 image, 與啓動腳本一塊兒

預覽版本的性能

咱們比較了Gradle和Activator(sbt)兩個方式的構建時間。

用來比較的工程

  • Basic - 一個簡單的Play工程, play-scala模板設爲activator.

  • Multiproject - 構建在gradle的multiproject的Play例子工程,a multiproject build based on the gradle’s,例3也是util的子工程.

測試方法

  • 全部依賴庫已經下載到本地gradle和ivy緩存裏.

  • 測試任務"dist "將生成最終發佈tar包,將測試整個構建和發佈流程,同時圍繞着依賴解析、編譯、打包執行。

  • Gradle是串行執行,在 vanilla sbt 使用時 configure-on-demand 和 daemon 啓用 .

  • Clean-build: 展現了從一個乾淨狀態的完整打包處理流程。

  • No change: 沒做任務改變返回 「dist」 .用來測試構建配置和更新有多快。

  • Incremental:改了一行讓根Play工程依賴了java或scale子工程來模擬典型的流程。

測試結果

從以上能夠看出,Gradle構建除了1個差一些外都勝出了,不論是沒有或小修改都很好,這正是咱們指望的。http://app.csq.im

基本依賴解析性能評估

咱們對依賴解析的性能更加感受興趣,因此咱們只想比較解析全部依賴要花多久,對 activator/sbt

備註
1.Gradle的「依賴」解析任務不只僅是解決依賴問題,實際上還打印出了4個子工程的依賴樹
2.Gradle的依賴解析處理時間是經過內置的分析工具報告的

從上面的結果能夠輕易的得出結論 Gradle的原生依賴解析引擎快過activator/sbt使用的 Ivy引擎 10倍以上。那就是咱們爲什麼將java工程構建在Gradle之上的緣由。


咱們仍努力將以前須要5-10分鐘的的activator/sbt項目用Gradle進行重構,咱們指望更好的結果!

譯者

朱淦 350050183@qq.com

http://my.oschina.net/u/1263162/blog

相關文章
相關標籤/搜索