SpringBoot工程jar包瘦身

2024-12-25  本文已影响0人  刘大坝
背景

SpringBoot 为我们快速开发提供了很好的架子,使得我们只需要少量配置就能开始我们的开发工作,但是当我们需要打包上传部署时,却是很神伤的一个问题,因为打出来的 Jar 包少则十几兆,多则一百来兆,我们需要上传至公网服务器时,是非常慢的,这就引出了今天的主题,SpringBoot项目Jar包如何瘦身部署

思路

分析 jar,我们可以看出,jar 包里面分为以下三个模块
分为 BOOT-INF,META-INF,org 三个部分,打开 BOOT-INF

可以看到有 classes,lib 两个文件夹,我们编译好的代码是放在 classes 里面的,而我们所依赖的 jar 包都是放在 lib 文件夹下classes 部分是非常小的(我的是3M左右),lib部分是非常大的(我的是170M+左右),所以上传很慢。


image.png

解决方法:如果能把lib部分剥离出来,每次打包时只更新当前项目的更新即可。(如果本项目所依赖有我们当前项目所需要的其他模块,其他模块更新后也需要打一个对应的lib包更新上去即可)

瘦身
正常打包

首先,我们项目的 pom.xml 文件中的打包方式如下:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

这是 SpringBoot 中默认的打包方式,我们先按照这种方式打包出来,得到一个 jar 包,我们将 jar 包解压,如果不能直接解压,则将后缀改为 zip 再进行解压,我们只需要拿到 BOOT-INF 中的 lib 目录即可。

image.png
改变打包方式

我们对 SpringBoot 中默认的打包方式做一些配置


image.png
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.xxx.XxxApplication</mainClass>
                <layout>ZIP</layout>
                <includes>
                    <include>
                        <groupId>nothing</groupId>
                        <artifactId>nothing</artifactId>
                    </include>
                </includes>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

再次打包

我们再次点击 maven package,得到一个 jar 包,可以看到此时的 jar 包只有几兆了

上传启动

我们将 lib 目录,以及最后打包的瘦身项目 jar 包,上传至服务器,目录如下


[root@Test tax-expand]# tree -L 1
.
├── 1-start.sh
├── 2-stop.sh
├── lib
├── your-app.jar 
└── start.sh

使用命令

nohup java -Dloader.path=./lib -jar ./your-app.jar &
[root@Test tax-expand]# cat 1-start.sh 
#!/bin/sh

# 脚本参数:
#  debug:启用 JVM 远程调试,端口设置在 JAVA_DEBUG 变量中。
#    log:打印 Java 进程标准输出内容,默认不打印,输出到 LOG_FILE 变量指定的文件中。
#    其他:带有 -D、-X、-javaagent 的参数,会添加到 JVM 参数中。

cd $(dirname $0)
./start.sh $*
[root@Test tax-expand]# cat 2-stop.sh 
#!/bin/sh

# 脚本参数:
#  debug:启用 JVM 远程调试,端口设置在 JAVA_DEBUG 变量中。
#    log:打印 Java 进程标准输出内容,默认不打印,输出到 LOG_FILE 变量指定的文件中。
#    其他:带有 -D、-X、-javaagent 的参数,会添加到 JVM 参数中。

cd $(dirname $0)
./start.sh stop

[root@Test tax-expand]# cat start.sh 
#!/bin/sh

# 脚本参数:
#  debug:启用 JVM 远程调试,端口设置在 JAVA_DEBUG 变量中。
#    log:打印 Java 进程标准输出内容,默认不打印,输出到 LOG_FILE 变量指定的文件中。
#    其他:带有 -D、-X、-javaagent 的参数,会添加到 JVM 参数中。

export JAR_NAME=your-app.jar
export APP_DIR=your-app
export DEPLOY_PATH=/home/application
export LOG_PATH=/data/logs/$APP_DIR
export LOG_FILE=$LOG_PATH/
export VM_OPTIONS=""
export GC_OPTIONS="-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime
                   -XX:+PrintHeapAtGC -XX:+UseGCLogFileRotation -XX:+HeapDumpOnOutOfMemoryError -XX:NumberOfGCLogFiles=5
                   -XX:GCLogFileSize=5M -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly
                   -XX:HeapDumpPath=${LOG_PATH}/heapdump.hprof -Xloggc:${LOG_PATH}/gc.log
                   -XX:HeapDumpPath=${LOG_PATH}/HeapDumpOnOutOfMemoryError/"
export JAVA_DEBUG="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=127.0.0.1:15005,server=y,suspend=n"
export STOP_TIMEOUT=120

for arg in $*; do
    [ "$arg" = debug ] && enable_debug=true;
    [ "$arg" = log ]   && enable_log=true;
    [[ "$arg" =~ -D|-X|-javaagent ]] && export VM_OPTIONS="$VM_OPTIONS $arg"
done;

JAVA="java"
[ -n "$JAVA_HOME" ] && JAVA="$JAVA_HOME/bin/java"

app_process=$(ps -ef | grep java | grep $JAR_NAME | grep -v grep | awk '{ print $2 }')

log () {
  echo "$(date '+%Y-%m-%d %H:%M:%S') $*"
}

# Stop app instance.
stop_app() {
  [ -z "$app_process" ] && log "Application already stoped." && return
  log "Stop Application...."
  ps -fp $app_process
  kill -9 $app_process

#  start=$(date +%s)
#  while [ -n "$(ps -hp $app_process)" ]; do
#    printf STOP | nc -v 127.0.0.1 $COMMAND_PORT
#    log "Application stopping..."
#    if [ $(($(date +%s) - $start)) -gt $STOP_TIMEOUT ]; then
#      echo "[ ERROR ] Application stop timeout, kill force."
#      kill -9 $app_process
#    fi
#    sleep 3
#   done
}
[ "$1" = stop ] && stop_app && exit 0

# check app instance
[ -n "$app_process" ] && log "Application is running. ^_^" && exit 1

# Start app instance
log "Start Application."
mkdir -p $LOG_PATH; touch $LOG_FILE; cd $DEPLOY_PATH/$APP_DIR

# Set execute command line
[ ! "$enable_debug" ] && export JAVA_DEBUG=""
EXEC_CMDLINE="$JAVA -Dloader.path=./lib  $VM_OPTIONS $GC_OPTIONS $JAVA_DEBUG -jar $JAR_NAME "
echo "*********************************************"
echo "Execute with the following JAVA command line:"
echo $EXEC_CMDLINE
echo "*********************************************"

# Call command line
nohup $EXEC_CMDLINE >/dev/null 2>&1 &

# Display log
[ "$enable_log" ] && tail -0f $LOG_PATH/process.log
exit 0
上一篇 下一篇

猜你喜欢

热点阅读