從零搭建開發腳手架 Spring Boot應用瘦身打包便于部署
- 背景
- 使用
- 工作原理
- 額外補充
- 運行應用程序進行預熱
- 使用Maven在編譯期打包依賴項
- 生產環境
背景
Spring Boot 默認打的Jar,包含應用程序代碼及其所有依賴項(內置tomcat jar就不小了),所以打包出來的jar文件很大,動不動就幾十,上百M,稱之為Fat jar。
在網速不給力的情況下,上傳服務器非常耗時。然而,其中我們引用到的Tomcat、Spring以及其他第三方組件,它們大部分時間是不會修改的而且占用了很大的空間,每次打包打進去。其實,我們經常改動的內容都是我們自己編寫的代碼,其大小大概也就幾十KB,每次升級我們只需替換這些文件即可。
Spring社區大概也考慮到了開發者有這樣的需求,所以提供了spring-boot-thin-launcher這個插件用來將項目的依賴和配置從jar包中分離出去。
使用
官網地址:https://github.com/spring-projects-experimental/spring-boot-thin-launcher
在Spring Boot pom文件中新增插件如下:
- <project ...>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot.experimental</groupId>
- <artifactId>spring-boot-thin-layout</artifactId>
- <version>1.0.27.RELEASE</version>
- </dependency>
- </dependencies>
- </plugin>
- </plugins>
- </build>
- </project>
然后還像以前一樣執行mvn clean package,這時生成的jar包僅幾十KB。
我這里因為項目有很多靜態文件所以比較大有2MB。
執行java -jar xxx.jar即可直接運行程序。
除了jar文件減小了,其他效果看著與Fat jar是一樣。
嘗鮮之后,來看下其內部原理吧。
工作原理
我們來看下Jar包內部的構成。
- Manifest-Version: 1.0
- Implementation-Title: map
- Implementation-Version: 0.0.1-SNAPSHOT
- Start-Class: com.laker.map.LakerMapApplication
- Spring-Boot-Classes:
- Build-Jdk-Spec: 1.8
- Spring-Boot-Version: 2.3.7.RELEASE
- Created-By: Maven Jar Plugin 3.2.0
- Main-Class: org.springframework.boot.loader.wrapper.ThinJarWrapper
即啟動類實際為:ThinJarWrapper
ThinJarWrapper類
我們編寫的代碼
項目的Pom文件
當執行java -jar xxx.jar時,實際執行的是ThinJarWrapper,它會先在指定目錄搜索看看依賴的jar包是否都存在,存在則直接使用,如果不存在,先從Maven中央倉庫下載到本地,然后,再執行我們自己編寫的main()入口方法。這種方式有點類似很多在線安裝程序:用戶下載后得到的是一個很小的exe安裝程序,執行安裝程序時,會首先在線下載所需的若干巨大的文件,再進行真正的安裝。
這個spring-boot-thin-launcher在啟動時搜索的默認目錄是用戶主目錄的.m2,我們也可以指定下載目錄,例如,將下載目錄指定為當前目錄:
- java -Dthin.root=. -jar xxx.jar
執行后發現當前目錄下自動生成了一個repository目錄,這和Maven的默認下載目錄~/.m2/repository的結構是完全一樣的,只是它僅包含xxx.jar所需的運行期依賴項。
- repository/
- com/
- net/
- org/
- ...
“注意:只有首次運行時會自動下載依賴項,再次運行時由于無需下載,所以啟動速度會大大加快。如果刪除了repository目錄,再次運行時就會再次觸發下載。
額外補充
運行應用程序進行預熱
緩存依賴項的最簡單方法是在目標環境中對應用程序進行預熱運行。正如我們之前看到的,這將導致依賴項被下載并緩存在本地 Maven 存儲庫中。如果我們運行多個應用程序,存儲庫最終將包含所有依賴項而沒有重復項。
由于運行應用程序可能會產生不必要的副作用,我們還可以執行“試運行”,只解析和下載依賴項,而無需運行任何用戶代碼:
- java -Dthin.dryrun=true -Dthin.root=. -jar xxx.jar
使用Maven在編譯期打包依賴項
添加以下依賴
- <plugin>
- <groupId>org.springframework.boot.experimental</groupId>
- <artifactId>spring-boot-thin-maven-plugin</artifactId>
- <version>${thin.version}</version>
- <executions>
- <execution>
- <!-- Download the dependencies at build time -->
- <id>resolve</id>
- <goals>
- <goal>resolve</goal>
- </goals>
- <inherited>false</inherited>
- </execution>
- </executions>
- </plugin>
構建項目后,目錄為target/thin/root/。
生產環境
生產環境中,大部分都是內外網隔離的,建議先在本地“試運行”,然后把repository目錄,瘦jar一起復制到服務器,設置thin.root指定目錄,設置thin.offline切換到“離線”模式。所有依賴項都必須在本地可用.
- java -Dthin.root=. -Dthin.offline=true -jar xxx.jar
參考:
https://www.liaoxuefeng.com/wiki/1252599548343744/1304267002478625