前言
热部署的原因
由于公司目前的服务是单机的,所以每次发布版本的时候,都需要先将服务停掉,然后启动新版本的服务,导致有大概有几分钟的时间内,服务处于一个不可用的状态,然后每次发布版本的时间也就都提到下班后处理。
所以想到用热部署的方式来平滑过渡新旧版本,也可以在一些比较紧急的情况下快速修复而不影响正在使用的人。
热部署选择
自己接触过自动化部署有jekins,但是由于各种原因(貌似因为有bug, 不过是在我来之前的),之前没有安装这个。
根据自己了解的, 现在要进行热部署,可以利用nginx的负载均衡来实现。
更改服务的端口,运行新版本的服务,然后nginx进行分流,关掉
旧版本的服务,这个时候对用户而言基本没什么感觉,就已经完成新版本的发布了。
该方法的优点是不需要引入第三方的插件,从而不提高维护成本,缺点是大部分是手动操作, 比较麻烦,所以也写了相应的shell脚本来替代部分手动的操作。
正式步骤
-
我这边的服务是springboot, 通过maven打成可执行的jar包,第一步是准备两个相同服务不同端口的jar包
这里我已经把压缩包解压了,除了配置文件,其他的都是一样的
由于我这里是放在同一个服务器上面, 所以服务端口改成不一样的, 用到了dubbo, dubbo注册的端口也改一下,否则会启动失败
然后上传到服务器 -
改nginx配置
这里下面的两个server表示两个负载均衡的服务, ip一样, 端口不一样。两台服务同时运行时候使用8888端口访问, 会被nginx分流, 将请求发送到两个服务中的一个, 其中一个关掉的情况下, 就只会请求到另外一个服务,从而达到部署的效果,weight表示权重,可以不配置。
- 按顺序开启服务和关闭服务
简单来说就是:
A服务是旧版服务,B服务是新版服务,先启动B服务, 等于做了一个简单的服务集群, 然后关掉A服务,这样请求就只会发送到B服务,并且由于B服务可以处理请求, 关掉A服务时,用户并不会察觉到,此时已经更新为新版本了
- 替代手动操作的shell脚本
echo sartrun
service serverB stop
rm /soft/serverB -rf
unzip -d /soft/ /soft/serverB-bin.zip
service serverB start
for ((i=0;i<20;i++))
do
code=`curl -I -m 10 -o /dev/null -s -w %{http_code} localhost:9001`
if [ "$code" == "000" ]; then
echo can't connect!
sleep 5
else
service serverA stop
rm /soft/serverA -rf
unzip -d /soft/ /soft/serverA-bin.zip
service serverA start
break
fi
done
echo finished!
for循环上面一段为开启B服务,for循环最多20次, 防止无效循环。
由于springboot服务启动完成需要一小段时间,短的可能10秒左右或者更快,慢的可能几分钟到十多分钟都有,所以要先判断一下B服务启动完成。
通过curl命令访问B服务获取返回的http_code, 如果B服务启动完成,会返回正常的状态码(200、302、404、500),如果还在启动中,则会返回000
如果还没启动成功,则等待5秒,然后再试,最多重试20次,也就是100秒,如果服务启动时间大于100秒,就增加次数或者增加每次等待的时间。
获取到正常的状态码之后可以关掉A服务,我这里是重启A服务。
结尾
我这里有些步骤没写出来, 比如创建软连接, 开放防火墙部分端口等,需求不一样,可能用不到,所以就是这些简化版的操作。