SpringBoot项目企业部署实践 (Jar包 & Linux)

项目打包

我们基于Linux系统,此处使用 Jar 包部署的方式。下面我们从打好的架包开始说起。

部署准备

我们新建一个文件夹,作为部署项目路径,此处我们新建一个 customer 为例。

目录结构:

|-- customer 
|   |-- bin
|	|-- conf
|	|-- lib
|	|-- log
|	|-- logs
|	|-- tmp
|	|-- tomcat.pid

目录/文件介绍

bin:用于存放jar的路径,以及启动关闭脚本等

conf:存放配置文件。

lib:用于存放相关library jar包。

log:用于存放项目日志的路径。

logs:可以存放第三方日志。

tmp:临时目录

tomcat.pid :进程pid,用于启动关闭等。

当然我们还可以根据我们的需求添加一下自定义的东西。

bin 目录

我们在 bin 中创建 shutdown.shstartup.sh,以及存放我们的 customer.jar

由于启动脚本直接运行的是 server.jar ,我们第一次使用需要对我们的jar创建一个软链接。我们在bin目录下执行一下命令。

ln -s customer.jar server.jar

image-20200511221754692

创建文件

startup.sh

#!/bin/sh
JAVA_OPTS=""
CLASSPATH=""
CATALINA_OPTS=""
PRG="$0"

RUN_USER="root"
PID_FILE="/data/customer/tomcat.pid"

current_user=`whoami`
if [ "$current_user" != "$RUN_USER" ];then
  echo "please run $0 as user $RUN_USER" 1>&2
  exit 1
fi

# resolve links - $0 may be a softlink
while [ -h "$PRG" ]; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done

# Get standard environment variables
PRGDIR=`dirname "$PRG"`
APP_HOME=`cd "$PRGDIR/.." >/dev/null; pwd`

SPRINGBOOT_OUT="$APP_HOME"/log/springboot.out

# set JAVA_OPTS
ENV_CONF="$APP_HOME"/conf/env.conf
if [ -f $ENV_CONF ];then
   JAVA_OPTS=`sed 's/"//g' $ENV_CONF | awk '/^[^#]/' | tr "\n" ' '`
fi

# set CLASSPATH
if [ -d "$APP_HOME"/lib ];then
  for lib_jar in `ls "$APP_HOME/lib"`;do
     CLASSPATH="$APP_HOME"/lib/"$lib_jar":"$CLASSPATH"
  done
fi

# User can set environment in setenv.sh
if [ -r "$APP_HOME/bin/setenv.sh" ]; then
  . "$APP_HOME/bin/setenv.sh"
fi

echo "Using JAVA_HOME:  $JAVA_HOME"
echo "Using APP_HOME:   $APP_HOME"
if [ ! -z "$CLASSPATH" ];then
  echo "Using CLASSPATH:  $CLASSPATH"
fi

if [ ! -z "$PID_FILE" ]; then
  echo "Using PID_FILE:   $PID_FILE"
fi

if [ ! -z "$PID_FILE" ]; then
  if [ -f "$PID_FILE" ]; then
    if [ -s "$PID_FILE" ]; then
      echo "Existing PID file found during start."
      if [ -r "$PID_FILE" ]; then
        PID=`cat "$PID_FILE"`
        ps -p $PID >/dev/null 2>&1
        if [ $? -eq 0 ] ; then
          echo "Server appears to still be running with PID $PID. Start aborted."
          exit 0
        else
          echo "Removing/clearing stale PID file."
          rm -rf "$PID_FILE" >/dev/null 2>&1
          if [ $? != 0 ]; then
            if [ -w "$PID_FILE" ]; then
              cat /dev/null > "$PID_FILE"
            else
              echo "Unable to remove or clear stale PID file. Start aborted."
              exit 1
            fi
          fi
        fi
      else
        echo "Unable to read PID file. Start aborted."
        exit 1
      fi
    else
      rm -rf "$PID_FILE" >/dev/null 2>&1
      if [ $? != 0 ]; then
        if [ ! -w "$PID_FILE" ]; then
          echo "Unable to remove or write to empty PID file. Start aborted."
          exit 1
        fi
      fi
    fi
  fi
fi

# Add server.jar to classpath, if CLASSPATH is not blank, it must be endswith ":"
CLASSPATH="$CLASSPATH""$APP_HOME"/bin/server.jar

cat /dev/null > ${SPRINGBOOT_OUT}

${JAVA_HOME}/bin/java $JAVA_OPTS -classpath $CLASSPATH org.springframework.boot.loader.JarLauncher >> $SPRINGBOOT_OUT 2>&1 &
if [ ! -z "$PID_FILE" ]; then
  echo $! > "$PID_FILE"
fi

echo "springboot server started."

其中以上路径,这里采用了绝对路径,可以按照实际修改。

PID_FILE="/data/customer/tomcat.pid"

shutdown.sh

#/bin/sh

RUN_USER="root"
PID_FILE="/data/customer/tomcat.pid"
SHUTDOWN_PORT="8941"

current_user=`whoami`
if [ "$current_user" != "$RUN_USER" ];then
  echo "please run $0 as user $RUN_USER"
  exit 1
fi

if [ ! -f "$PID_FILE" ];then
  echo "pid file $PID_FILE not exist, please check if server running, stop aborted."
  exit 1
fi

netstat -an | grep LISTEN | grep -w $SHUTDOWN_PORT
if [[ $? -eq 0 ]]; then
  shut_info=`curl --connect-timeout 10 -m 30 -XPOST http://127.0.0.1:"$SHUTDOWN_PORT"/shutdown.json`
  echo "shutdown info: $shut_info ,result code: $?"
fi

pid=`cat $PID_FILE`
for num in 1 2 3 4 5 6 7 8 9 10
do
  echo "stop times: $num"
  still_alive=`ps -ef | awk '$2 ~ /^'$pid'$/{print $2}'`
  if [ ! -z "$still_alive" ];then
    kill $pid
    sleep 1
  else
    break
  fi
done

still_alive=`ps -ef | awk '$2 ~ /^'$pid'$/{print $2}'`
if [ ! -z "$still_alive" ];then
  kill -9 $pid
fi

rm -rf $PID_FILE
exit 0

其中以上路径,这里采用了绝对路径,可以按照实际修改。

PID_FILE="/data/customer/tomcat.pid"

conf 目录

我们在 conf 中创建 application.propertiesenv.conf ,其中 application.propertiesspringboot 项目的配置文件,这样很容易实现多环境。

application.properties

apollo.bootstrap.enabled=true
app.id=customer
apollo.meta=http://127.0.0.1:9080
apollo.cacheDir=/data/configcache/

这里的配置采用了Apollo,所以配置就这么几行。

env.conf

#!/bin/bash
#-------------------------------------------------tomcat配置文件简介----------------------------------------#
#
# 目的:方便增加参数,把所有环境变量参数全部提取出来,开发人员可以方便的增加参数字段来创建tomcat某
# 些运行的机制,从而更好的利用虚拟机的系统资源。
#
# 增加方法:添加一个"xxx"字串参数,然后用半角双引号把需要增加的参数新建一行,并做好注释,以方便运
# 维人员管理与维护。
#
# 关闭方法:在不需要的参数前面加上"#"即可,注意参数相关性,可能关闭的参数会引起其他参数失效,注意看
# 注释中的备注项。
#
# 版本:v 1
#
#-----------------------------------------------------------------------------------------------------------#
#
#-----------------------------------------------------JDK-TOMCAT--------------------------------------------#
# TOMCAT日志
# ++++++++++++++++++++
#LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/logging.properties"
# ++++++++++++++++++++
#-----------------------------------------------------------------------------------------------------------#
#
#-------------------------------------------------------参数区域--------------------------------------------#

# 内存参数设置区
# ++++++++++++++++++++
"-server"
"-Xms512m"
"-Xmx1024m"
# "-XX:NewSize=512m"
# "-XX:MaxNewSize=512m"
# "-XX:SurvivorRatio=5"
# "-XX:TargetSurvivorRatio=90"
# "-XX:MaxTenuringThreshold=12"
# "-XX:+UseConcMarkSweepGC"
# "-XX:+CMSIncrementalMode"
# "-XX:+CMSIncrementalPacing"
# "-XX:+CMSParallelRemarkEnabled"
# "-XX:+UseParNewGC"
# "-XX:PermSize=64m"
# "-XX:MaxPermSize=64m"
# "-XX:+UseTLAB"
# ++++++++++++++++++++

# 允许类清理(需要"ConcMarkSweepGC"参数,若关闭请同时关闭此处参数)
# ++++++++++++++++++++
#"-XX:+CMSClassUnloadingEnabled"
#"-XX:+CMSPermGenSweepingEnabled"
# ++++++++++++++++++++

# 调试与内存优化避免Hotspot编译器失效
# ++++++++++++++++++++
#"-XX:+PrintCompilation"
#"-XX:CodeCacheMinimumFreeSpace=2M"
#"-XX:ReservedCodeCacheSize=64M"
#"-XX:CompileCommandFile=/my/portal/bin/hotspot_compiler"
# ++++++++++++++++++++

# 开启下列项仅为GC输出分布式信息开启某些调试项
# ++++++++++++++++++++
#"-verbose:gc"
#"-XX:+PrintGCTimeStamps"
#"-XX:+PrintGCDetails"
#"-XX:+PrintTenuringDistribution"
#"-Xloggc:/my/portal/logs/portal/gc.log"
# ++++++++++++++++++++

# 允许 JMX 远程监视
# ++++++++++++++++++++
#"-Dcom.sun.management.jmxremote"
#"-Dcom.sun.management.jmxremote.authenticate=false"
#"-Dcom.sun.management.jmxremote.port=9000"
#"-Dcom.sun.management.jmxremote.ssl=false"
#"-Djava.rmi.server.hostname=172.19.3.141"
#"-Dcom.sun.management.jmxremote.password.file=/my/portal/bin/jmxremote.password"
#"-Dcom.sun.management.jmxremote.access.file=/my/portal/bin/jmxremote.access"

# ++++++++++++++++++++
# 允许远程调试端口
# ++++++++++++++++++++
# "-Xdebug -Xrunjdwp:transport=dt_socket,address=8280,server=y,suspend=n"
# ++++++++++++++++++++
#-----------------------------------------------------------------------------------------------------------#
# 更改user.home
# "-Duser.home=/home/jdk8"
"-Dfile.encoding=UTF-8"
# "-Dlogback.configurationFile=/home/tomcat/conf/logback.xml"
"-Dspring.config.location=/data/customer/conf/application.properties"

配置解释

此处我们只配置了

“-Xms512m”
“-Xmx1024m”

实际上已经基本够用了。我们还可以配置一些其他JVM优化,我们也可以远程调试之类的。

  • 重点:最后指定了运行的配置文件的路径。

部署运行

我们准备好这些之后,我们就可以部署我们的 customer 服务了。假如我们现在在bin目录中。

启动服务

./startup.sh

关闭服务

./shutdown.sh

实际部署

处于实际的考虑我们提出以下问题:

  1. 每次都要在此目录执行启动关闭,是否太麻烦了?

  2. 如果我们再次发包,每次都发到bin中,如果服务又比较多,是不是也很麻烦?

因此,我们进行以下优化:

​ 定义一个发布的上包路径,所有需要上传的包都上传到一个地方,例如我们一个电商系统中 goods、order 等,我们统一放在 /htdocs 下。

​ 我们创建一个 customer 命令,进行全局使用。

customer文件

#!/bin/sh

# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 80 50
# description: A very fast and reliable Tomcat.

# 指定 JAVAHOME 路径
export JAVA_HOME=/usr/local/src/java/jdk1.8.0_212

project="/data/"
tomcat[1]="${project}customer"
module="customer"
#指定上包路径
jar="/htdocs"

start(){
	cache
	for i in ${tomcat[@]}
	do 
		${i}/bin/startup.sh
		sleep 60
	done
	test
}

stop(){
	for i in ${tomcat[@]}
	do 
		${i}/bin/shutdown.sh
		pid=$(ps -ef | grep ${i} | grep -v grep | awk '{print $2}')
		if [ "${pid}" != "" ];then
			kill -9 ${pid}
		fi
		sleep 5
	done
	cache
	test
}

test(){
	for i in ${tomcat[@]}
	do
		pid=$(ps -ef | grep ${i} | grep -v grep | awk '{print $2}')
		if [ "${pid}" != "" ];then
			echo "${i} is running!"
		else 
			echo "${i} may not be running!"
		fi 
	done
}

change(){
	transfer(){
			a=`find ~ -name *${module}* | wc -l`

			if [ ${a} -gt 0 ];then
					mv ${jar}/*${module}*.jar ${jar}/backup/
					mv ~/*${module}*.jar ${jar}
			fi
			for i in ${module[@]}
			do
					b=$(ls -A ${jar} | grep "${i}")
					if [ "${b}" != "" ];then
							echo ${i}
					fi
			done
	}
	app=$(transfer)
	for i in ${app[@]}
	do
			rm -rf ${tomcat[1]}/bin/*${i}*.jar
			cp ${jar}/*${i}*.jar ${tomcat[1]}/bin			
	done
}
cache(){
	sync
	echo 3 > /proc/sys/vm/drop_caches
}
case "$1" in
	start)
	start
	;;
	stop)
	stop
	;;
	restart)
	stop
	start
	;;
	reload)
	stop
	change
	start
	;;
	status)
	test
	;;
	load)
	change
	start
	;;
	*)
	echo "Use tomcat start|stop|status|restart|reload|load"
	;;
esac

我们需要修改,JAVA_HOME 路径,上包路径

然后我们将此命令放到 /etc/init.d 目录下,并分配权限

chmod +x customer

命令中包含 start|stop|status|restart|reload|load

我们需要初次上包或者重新上包时使用,在我们 reload 时,做如下操作

image-20200511222501252

然后进行:shutdown.sh --> startup.sh

service customer reload

我们重启时使用

service customer restart

写在最后

今天先写到这里了,有点累了,改天再补充一下吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值