微服务优雅停机研究

微服务优雅停机研究

什么叫优雅停机?

—— 每个服务节点上新的服务部署包下载完成后,就要停止当前运行的服务进程,部署新版本服务。
  在停止服务时,由于服务上有正在运行的请求,需要等待这些请求处理完毕,同时不让新的请求进来,这就是所谓的“优雅停机”。

  我们公司用的服务注册中心是阿里的nacos,有篇文章能通过设置流量权重能实现:https://nacos.io/zh-cn/docs/console-guide.html

 其中要注意下:

  Nacos提供对服务进行上下线的功能,这只会标记服务不可用,与Spring Cloud的应用的UP/DOWN状态类似。并不会停止服务的进程,当新服务上线之后,还需要到服务器上关闭进程,不是很方便。(引用文章:https://blog.csdn.net/suxingrui/article/details/103795148   )

 

测试优雅上下线整个过程

  首先我声明一下,这个只是我这边运维成功测试通过,并不表示实际就是这样配置,因为开发没空给我调试:模拟用户当表单填写进行到一半的时候,服务突然升级是否会转移到新节点?

  所以这个仅仅是我的研究过程,大家请三思而后行,思路可以参考下。

 

一、前言
假设两台机器:
  A(ljy123)是正式服务器,平时由它对外提供服务
  B(ljy456)是临时服务器,只有在A发布时临时提供服务。目的:不影响业务中断,继续处理已经过来的表单请求
当A升级完之后,B下线,A重新提供服务。
 
二、测试流程
1、原来A每个微服务只有一个服务实例,
中台服务middle和网关gateway,都只有1个实例数,目前处于健康状态

 

2、发布B服务器上的服务,作为临时提供服务用

配置一个jenkins服务发布:仅仅用来发布B服务器上的两个服务,什么都不需要判断

 

 发布完后,每个微服务就有两个实例,如下图(程序会自动注册到nacos上的)

 

3、运行发布A
前提查到 B服务器上已经上线了对应的服务:middle和gateway
这个时候需要调用nacos的接口,获取当前jar包服务信息,我贴下关键的jenkins配置信息(Pre Steps的执行shell步骤里)
 1 #1、调用nacos接口,获取当前jar包服务信息
 2     serviceinfo=`curl -X GET https://cluster.ljytest.com/nacos/v1/ns/instance/list?serviceName=$DEPLOY_SERVICE`
 3     
 4 #2、获取jar包服务实例
 5     Binstance=`echo "${serviceinfo}" | awk -F"[,}]" '{for(i=1;i<=NF;i++) { if($i~/instanceId/ && /B机器上的ip/) {print $(i)}}}'`
 6     
 7 if [[ "$Binstance" = ""  ]]
 8 then
 9     echo "B机器上没有提供服务:$DEPLOY_SERVICE,为了不中断,不能发布A机器上的服务......." 
10     exit 1
11 fi
12       
13 
14     Bhealthline=`echo "${serviceinfo}" | awk -F"[,}]" '{for(i=1;i<=NF;i++) { if($i~/instanceId/ && /B服务器上的ip/) {print $(i+2)}}}'`
15     
16     healthjudge=`echo $Bhealthline | grep "true"`
17 
18 ### 判断不在线,不发布
19 if [[ "$healthjudge" = ""  ]]
20 then
21     echo "B机器上没有提供服务:$DEPLOY_SERVICE,为了不中断业务,不能发布A机器的服务......." 
22     exit 1
23 fi
24     
25 done
26 
27 
28 echo "开始发布A机器的服务......."
 
##### 测试B机器没有提供服务,A机器不发布

1、B机器发布服务

middle中台服务是8200端口

2、A机器发布服务

两种情况
(1)B机器注册了服务,A机器可以下线发布
(2)B机器没有注册服务到nacos,A机器不可以下线发布!!!
假设B机器的middle服务没有注册上去,测试A是否能发布(注意上图,我把middle服务进程号干掉了)

B机器middle服务不存在,nacos页面红色一栏表示

 

 

 

jenkins报错,不能发布

注意:任意一个服务只要B机器没有上线,就会终止jenkins发布服务的

3、下线临时B服务器,重新让A提供服务

因为前面提到,下线只是nacos的一个标记,实际是需要登录服务器进行服务关停的

调nacos接口进行扫描 ——》 筛选服务健康值 ——》 进行发布/不发布

 1 cd /home/ljy/micro_service/jar_tmp
 2 cat dst/nacosservice | while read line
 3 do
 4      stopservice=$line
 5 #1、调用nacos接口,获取当前jar包服务信息
 6    serviceinfo=`curl -X GET https://cluster.ljytest.com/nacos/v1/ns/instance/list?serviceName=$stopservice`
 7 
 8 #2、获取A上jar包服务实例
 9     Binstance=`echo "${serviceinfo}" | awk -F"[,}]" '{for(i=1;i<=NF;i++) { if($i~/instanceId/ && /A机器IP/) {print $(i)}}}'`
10     
11 if [[ "$Binstance" = ""  ]]
12 then
13     echo "A没有提供服务,为了不中断,不能下线B的$serviceName......." 
14     exit 1
15 fi
16  
17  #3、获取A上jar包服务实例是否在线
18     Bhealthline=`echo "${serviceinfo}" | awk -F"[,}]" '{for(i=1;i<=NF;i++) { if($i~/instanceId/ && /A机器IP/) {print $(i+2)}}}'`
19     
20     healthjudge=`echo $Bhealthline | grep "true"`
21 
22 
23 ### 判断A机器服务不在线,就不下线B机器的服务
24 if [[ "$healthjudge" = ""  ]]
25 then
26     echo "A没有提供服务:$serviceName,为了不中断,不能下线B的服务......." 
27     exit 1
28 fi
29     
30 echo "开始下线B的服务......."
31 
32 #4、调nacos下线接口
33 curl -X POST 'https://cluster.ljytest.com/nacos/v1/ns/instance?serviceName='$stopservice'&port=8200&ip=10.0.0.126&enabled=false&metadata={preserved.register.source=SPRING_CLOUD}'
34 
35 sleep 5
36 
37 #5、关临时B机器的服务
38 cat dst/outfiles| while read line
39 do
40 
41 ps -ef | grep java |  grep "$line" | grep -v grep |awk '{print $2}' | xargs kill -9
42 
43 done
44 
45 done


jenkins日志(反正curl之后的结果要处理一波的,最终获取一个Bhealthyline的变量值,大家实践下就知道了

 

posted @ 2021-02-21 22:42  windysai  阅读(761)  评论(0编辑  收藏  举报