赞
踩
前言: 基于公司业务,公司项目架构都是按业务模块拆分的微小服务。每次更新迭代jar包传输是个头疼的问题。因为我们需要上传部署至公网服务器,而springboot打出来的jar包有时候非常大,传输会非常慢。特此对SpringBoot项目Jar包进行瘦身部署。
其实,在众多微小的服务中,引用的依赖jar包都大致相同,被打包到各个服务模块中一遍又一遍。我们可以把依赖jar包都提取到一个公共包下。让各个服务从公共目录下加载依赖jar包。如下:
看看原来生成的jar包
可以看到,较小的服务包都是4、50m这样子。在远程部署时,传输会非常慢。
springboot 启动时可以指定加载外部依赖目录来启动工程,所以我们不必每次打包都包含一堆 jar 包,只需要把 jar 统一放一个目录,启动时指定依赖目录启动就行。
1. 原来的包结构
在BOOT-INF包中会生成一个lib包,所有引入的依赖会被放在这下面。所以我们只需要提取这个lib包到外部,并且所有依赖jar包不打包到服务包中。
2. 从服务包中抽离依赖包
使用 SpringBoot 打包插件打包
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!--换成你自己项目的启动类(path)--> <mainClass>xx.xx.xxxApplication</mainClass> <layout>ZIP</layout> <includes> <!--排除lib包,nothing任何依赖项都不进行打包--> <include> <groupId>nothing</groupId> <artifactId>nothing</artifactId> </include> </includes> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
3. 将依赖jar包提取到指定目录下。
使用maven的依赖管理插件
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <type>jar</type> <includeTypes>jar</includeTypes> <includeScope>runtime</includeScope> <!--指定拷贝依赖项存放的目录位置--> <outputDirectory>${mvn.target}\target/lib</outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin>
关于这些配置,官方文档都有解释 ,大致就是如果提取位置存在版本相同的依赖包会什么样的操作。 Apache Maven
4. clean 后 重新进行打包
看看新生成后的服务包和提取到的依赖包 lib/,小了很多。
看看lib包中提取的依赖(这里把各个服务的依赖全放在一个目录中了,也才100多m,说明之前单独打包中重复的依赖包很多)
解压后看看服务包中的BOOT-INF 已经不存在lib依赖包。这个时候启动jar包会找不到主类的
5. 通过命令指定外部依赖目录的方式进行启动
java -Dloader.path=./lib -jar auth.jar
# loader.path: 引用的目录(你提取存放依赖的目录位置)
服务启动:
如果你的服务有很多,引入的依赖包也不同。各式各样,可能会出现依赖冲突的问题,各种明明服务没有引入的包,都会被加载,并且提示无法创建这些问题(这里就暂且将他理解为依赖冲突,也不是很清楚问题出在哪。有可能是因为这种方式加载依赖jar包,会默认加载lib下面的所有,但有些服务并没引用某些jar包,而是其他服务提取出来的,导致被加载无法创建的问题)
对于这个问题,唯一能想到就是 指定需要加载哪些包,而不是都去加载。
1. 通过maven插件在打包时将加载的jar包写入到配置中。
<!--指定加载外部jar位置-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!--外部jar位置,这里表示从同级目录的lib包下加载-->
<classpathPrefix>./lib</classpathPrefix>
<mainClass>xx.xxx.xxApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
2. 再次clean 后重新打包
这里唯一的区别就是在生成的包:META-INF/MANIFEST.MF 这个文件内容会明显不同
多了一个class-path : 并且指定了很多jar包位置。
3. 重新启动服务
这里就不需要 loader.path 的方式指定外部依赖的位置。在服务包打包时已经指定了需要加载的依赖,以及jar包的位置
java -jar xxx.jar
不用每次都上传一个很大的 jar 包,在依赖不变动的情况下,只需要更新服务包就行。
而服务包中通常就是一些配置和代码,会非常小。部署更新会很快!
在依赖变动的情况下,重新替换服务器上的依赖包。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。