前提
请看我的前置文章,我不太可能再次重复强调云效流水线每个配置的作用,很重要!!!
请看我的前置文章,我不太可能再次重复强调云效流水线每个配置的作用,很重要!!!
请看我的前置文章,我不太可能再次重复强调云效流水线每个配置的作用,很重要!!!
跟最基本的单模块spring boot项目相比,微服务项目其实最大的区别就是模块变多了,我这里也只是最简单的微服务项目,有两个模块。(也许只是对我当前的情况有用?所以各位可以只做参考,也并没有用到容器部署,后面有时间的话,会研究下如何利用流水线进行容器部署。)
思路
关于这个项目的流水线部署,都是我自己摸索的,与单模块部署区别不大,大概看懂了deploy.sh这个脚本文件后,脑子里就已经有思路该如何部署多模块项目了,于是自己按照思考的方法,没想到真成了。
思路就是:既然一个jar包,原理不过是通过shell语言,执行一些Linux的命令而已,那么我们完全可以顺序执行两遍命令,两遍命令的格式一模一样,唯一的区别就是jar包的名称不同,那就好办了,改一下deploy.sh这个脚本就行了吧。
部署过程
1、流水线模板选择
一样是选择构建 + 部署两步的模板
2、Java构建编辑
我这里再重复说一下
制品名称是可以自定义的,以我这里的制品名称package-yuanchangliang为例,正常默认情况下,制品名称是package,但是由于我在此主机已经部署过单模块springboot项目:spring-boot-template了(看上一篇文章!!!),两个项目的制品名称尽量避免一样,防止相互影响。
制品名称就是流水线拉取代码后,构建的产物名称,是一个压缩包,里面包含了你在打包路径中所填写的所有文件和文件夹。以我这张图为例,会生成一个名叫:package-yuanchangliang.tgz的压缩包,这个压缩包中包含了ycl-gateway.jar、ycl-system.jar、deploy.sh三个文件。
打包路径 需要特别注意,由于这是微服务项目,有多个模块,最主要就是有些模块是父子结构的,父模块只是个空壳,用于装多个实际的微服务模块,所以打包路径也要针对是否为父子模块来填写。
这是我用于部署的项目,可以看到GateWayApplication启动类所在的模块ycl-gateway是直属于项目的,而SystemApplication启动类所在的模块ycl-service-system外面还有一层ycl-service模块,并不直属于项目。这种情况在微服务项目中是再正常不过的。所以我的打包路径配置如下:
各位对照一下我的项目结构,就可以知道该怎么填了。
最后提示一句,jar包名称可以在对应pom文件的build中,通过如下配置指定哦
<finalName>ycl-gateway</finalName>
主机部署编辑
下载路径也是可以自定义的,这个路径对应的就是你部署用的主机,流水线运行后,各位可以登上自己的主机查看,对应目录是否存在对应的压缩包(推荐各位实际看看,能够更加理解所谓的下载路径是什么)。
也就是我们前文中提到的package-yuanchangliang.tgz压缩包,这个压缩包构建后,是存放在阿里云的公共仓库的,并没有在你的主机中,只有定义了下载路径,这个压缩包才会实际下载到你的主机的下载路径中。
部署脚本:
mkdir -p /home/admin/yuanchangliang
tar zxvf /home/admin/app/package-yuanchangliang.tgz -C /home/admin/yuanchangliang/
sh /home/admin/yuanchangliang/deploy.sh restart
上一篇文章也说了,部署脚本的作用,就是解压下载的package-yuanchangliang.tgz压缩包到指定路径,并执行我们项目中的脚本文件,不赘述。
脚本文件
看了我上一篇文章的各位可以发现,文章写到这里,其实除了打包路径需要特别注意,和上一篇文章没有任何区别,而脚本文件就是这篇文章的精华所在,虽然改造起来挺简单,哈哈。
注意:此脚本文件很长,但是意思非常简单,相比较之前单个jar包时的部署,就是从执行一遍nohub java -jar XXX.jar & 这个命令,变为了执行两遍这个命令而已。如果你们的项目有七八个微服务,就执行七八遍这个命令就行,看起来命令行很多,如果跟上一篇文章的deploy.sh脚本文件进行对比,理解起来太太太简单了。
#!/bin/bash
# 修改APP_NAME为云效上的应用名
APP_NAME1=ycl-gateway
APP_NAME2=ycl-system
# 应用端口
APP_PORT1=10003
APP_PORT2=10004
# 应用健康检查URL
#由于我这里只有两个微服务模块,统一端口进入,故只需要检查一次就可以了
HEALTH_CHECK_URL2=http://127.0.0.1:${APP_PORT1}/login/hello
# 从package.tgz中解压出来的jar包放到这个目录下
APP_HOME=/home/admin/yuanchangliang
# jar包的名字
JAR_NAME1=${APP_HOME}/${APP_NAME1}/target/${APP_NAME1}.jar
JAR_NAME2=${APP_HOME}/ycl-service/ycl-service-system/target/${APP_NAME2}.jar
#应用的启动日志
JAVA_OUT1=${APP_HOME}/logs/${APP_NAME1}-start.log
JAVA_OUT2=${APP_HOME}/logs/${APP_NAME2}-start.log
# 等待应用启动的时间(复杂的项目建议写长一点,根据实际启动时间来定)
APP_START_TIMEOUT=30
# 脚本会在这个目录下生成nginx-status文件
HEALTH_CHECK_FILE_DIR=/home/admin/status
PROG_NAME=$0
ACTION=$1
# 创建出相关目录
mkdir -p ${HEALTH_CHECK_FILE_DIR}
mkdir -p ${APP_HOME}/logs
usage() {
echo "Usage: $PROG_NAME {start|stop|restart}"
exit 2
}
health_check() {
exptime=0
echo "checking ${HEALTH_CHECK_URL2}"
while true
do
status_code=`/usr/bin/curl -L -o /dev/null --connect-timeout 5 -s -w %{http_code} ${HEALTH_CHECK_URL2}`
echo "check result is : " $?
if [ "$?" != "0" ]; then
echo -n -e "\rapplication not started"
else
echo "code is $status_code"
if [ "$status_code" == "200" ];then
break
fi
fi
sleep 1
((exptime++))
echo -e "\rWait app to pass health check: $exptime..."
if [ $exptime -gt ${APP_START_TIMEOUT} ]; then
echo 'app start failed'
exit 1
fi
done
echo "check ${HEALTH_CHECK_URL2} success"
}
start_application1() {
echo "starting java process"
nohup java -jar ${JAR_NAME1} > ${JAVA_OUT1} 2>&1 &
echo "started java process"
}
start_application2() {
echo "starting java process"
nohup java -jar ${JAR_NAME2} > ${JAVA_OUT2} 2>&1 &
echo "started java process"
}
stop_application1() {
checkjavapid=`ps -ef | grep java | grep ${APP_NAME1} | grep -v grep |grep -v 'deploy.sh'| awk '{print$2}'`
if [[ ! $checkjavapid ]];then
echo -e "\rno java process"
return
fi
echo "stop java process"
times=60
for e in $(seq 60)
do
sleep 1
COSTTIME=$(($times - $e ))
checkjavapid=`ps -ef | grep java | grep ${APP_NAME1} | grep -v grep |grep -v 'deploy.sh'| awk '{print$2}'`
if [[ $checkjavapid ]];then
kill -9 $checkjavapid
echo -e "\r -- stopping java lasts `expr $COSTTIME` seconds."
else
echo -e "\rjava process has exited"
break;
fi
done
echo ""
}
stop_application2() {
checkjavapid=`ps -ef | grep java | grep ${APP_NAME2} | grep -v grep |grep -v 'deploy.sh'| awk '{print$2}'`
if [[ ! $checkjavapid ]];then
echo -e "\rno java process"
return
fi
echo "stop java process"
times=60
for e in $(seq 60)
do
sleep 1
COSTTIME=$(($times - $e ))
checkjavapid=`ps -ef | grep java | grep ${APP_NAME2} | grep -v grep |grep -v 'deploy.sh'| awk '{print$2}'`
if [[ $checkjavapid ]];then
kill -9 $checkjavapid
echo -e "\r -- stopping java lasts `expr $COSTTIME` seconds."
else
echo -e "\rjava process has exited"
break;
fi
done
echo ""
}
start() {
start_application1
start_application2
health_check
}
stop() {
stop_application1
stop_application2
}
case "$ACTION" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
usage
;;
esac
如果各位是个人项目,完全可以使用这种笨方法来尝试一下;但是如果各位是企业生产项目,千万别学我这样做,我这样做太笨重了,肯定有更好的方法,而且一般企业项目都是用容器部署的,谁还用纯jar包部署啊!!!!
如果是个人项目,简直不要太爽,现在我沉迷于改一个bug就运行一遍流水线,美滋滋。后续还有一篇关于前端项目流水线部署的,写完我会贴出链接,我已经实现了。
顺便推下我在此文章中实际使用的项目地址:
https://gitee.com/judgebymom/yuanchangliang.git
以及此项目部署上线后的公网访问地址:
http://39.101.204.247/login#/login账号密码:yuanchangliang/ycl123
网站可能会崩,因为有了流水线后,我随时都可能改动项目代码,然后随便部署上线╮(╯▽╰)╭
–我是“道祖且长”,一个在互联网"苟且偷生"的Java程序员
“有任何问题,可评论,我看到就会回复”