在七月底,Spring Boot和Dropwizard分別發布了1.4和1.0版本,它們都是基于Fat JAR的。隨著人們更多地采用這些框架和微服務架構,Fat JAR成為了通用的部署機制。
\\Fat JAR技術會將Java應用的所有依賴打包到一個bundle之中,便于執行,這種方式用到了很多的Java微服務框架之中,包括Spring Boot和Dropwizard,甚至還有一個專門的Fat JAR Eclipse插件。
\\對于具有少量微服務的組織來說,Fat JAR所占用的帶寬可能并不那么明顯。但是,如果你有上千個微服務的話,那么它們所使用的帶寬就會成為一個問題了。
\\在今年夏天的早些時候,HubSpot曾經提到過借助maven-shade-plugin進行Fat JAR部署所遇到的問題,并介紹了他們將100,000個小文件打包到一個JAR中所遇到的性能問題。他們還提到,1,000個以上的應用進行持續不斷地構建和部署,會產生大量重復的JAR依賴。
\\他們曾經嘗試使用maven-dependency-plugin來減緩這種快速膨脹,但是他們的努力并沒有減少所生成的構建工件(artifact)的大小。
\\為了解決Fat JAR所帶來的痛苦,HubSpot創建了用于Maven的SlimFast插件,它所創建的構建工件只會包含指定項目的類。它會依附到部署階段上,并將應用的所有依賴分別上傳到Amazon Simple Storage Service(S3)之中。通過使用這個插件,HubSpot的報告顯示,構建時間快了60%,并且可用的存儲容量增加了99%。
\\下圖展現了使用SlimFast之后,所帶來的構建速度提升:
\\為了更深入地了解HubSpot所面臨的Fat JAR問題,InfoQ采訪了他們的軟件工程師Jonathan Haber。
\\InfoQ:你們所遇到的Fat JAR問題大部分都是由持續集成和部署引起的嗎?
\\\\\Jonathan Haber:是的,我認為我們所遇到的問題很大程度上都是由我們的開發風格所導致的。我們有很多小團隊,他們都在推送代碼、構建和部署,這樣的活動每天都有上百次。因為我們的構建單元很小,所以創建和上傳Fat JAR所消耗的時間有時比編譯和測試代碼的時間還長。話說回來,如果你采用單體結構的話,構建所需的時間可能會超過20分鐘,那么相對來講Fat JAR的消耗就沒有那么明顯。但是,我認為有更多的公司在轉向這種更快、更輕量級的部署風格,因此可能會面臨同樣的挑戰。
\
InfoQ:你認為像SlimFast這樣的替代性打包技術是否應該作為框架的原生方案,比如添加到Spring Boot和Dropwizard中?
\\\\\Haber:因為這種方式需要與構建和部署系統集成,我的感覺是如果將其包含在Spring Boot或Dropwizard中的話,那就太帶有傾向性了。但是,有一種處理方式就是將SlimFast插件放到一個Maven profile之中,通過環境變量來激活。通過這種方式,構建系統能夠表明它支持這個特性,否則的話,依然將會采用Fat JAR的方式。
\
InfoQ:如果云提供商(如Heroku、CloudFoundry等)采用類似的技術來減少應用之間重復的JAR,那么他們在帶寬方面是不是可以節省很多錢?
\\\\\Haber:我并不確定能夠節省到什么程度,但是我認為采用類似的策略是可行的。不過,我們的優勢在于所有的應用都使用了相同版本的第三方庫,所使用的庫有大量的重疊。對于云提供商來說,他們的用戶所依賴的庫會廣泛得多,會跨所有的不同版本,所以如果你想在應用服務器上緩存依賴的話,會需要大量的空間。但是,如果你不這樣的話,速度/帶寬方面的大量節省就會不復存在。這并不是說,完全沒有節省,我只是認為他們的實現會比我們的方式更加復雜。另外一個問題在于,這些云提供商通常只會基于用戶的POM來運行Maven,所以他們對于構建生命周期并沒有太多的控制權,無法添加這種類型的優化。
\
InfoQ:在Fat JAR應用方面,你希望看到有哪些改善呢?
\\\\\Haber:如果Java能夠處理嵌套JAR的話,那么構建和運行Fat JAR都會容易很多,我并不確定這一點是否會包含在Java 9的功能列表中。像Spring Boot和One-JAR這樣的工具都能很好地解決這種局限性,但是他們增加了復雜性并且無法做到完全的透明。
\
查看英文原文:Solving Fat JAR Woes at HubSpot