项目打包
我们基于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.sh
、startup.sh
,以及存放我们的 customer.jar
由于启动脚本直接运行的是 server.jar
,我们第一次使用需要对我们的jar创建一个软链接。我们在bin目录下执行一下命令。
ln -s customer.jar server.jar
创建文件
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.properties
、env.conf
,其中 application.properties
为 springboot
项目的配置文件,这样很容易实现多环境。
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
实际部署
处于实际的考虑我们提出以下问题:
每次都要在此目录执行启动关闭,是否太麻烦了?
如果我们再次发包,每次都发到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
时,做如下操作然后进行:shutdown.sh --> startup.sh
service customer reload
我们重启时使用
service customer restart
写在最后
今天先写到这里了,有点累了,改天再补充一下吧!