Skip to content

microservice graceful up down

chengyouling edited this page Aug 20, 2024 · 20 revisions

微服务优雅上线、下线

服务注册时,容器可能还未就绪,但是已经对外提供服务,请求进来就会触发503服务不可用异常;微服务下线时,容器已进入销毁过程,但是注册中心还在健康检查时间范围没有剔除服务,仍然可以对外提供服务,请求进来也会触发503服务不可用异常。

针对上面两种情况,spring-cloud-huawei结合spring-boot-actuator实现微服务优雅上下线,以解决动态扩缩容服务不可用问题。

版本要求:1.11.2-2021.0.x/1.11.2-2022.0.x及以上版本。

Servicecomb为注册中心场景

  • 微服务pom必须的依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>com.huaweicloud</groupId>
  <artifactId>spring-cloud-starter-huawei-service-engine</artifactId>
</dependency>
  • 微服务开启优雅上下线配置

实现原理为:微服务启动时,先注册一个DOWN状态实例,此时外部无法调用该实例,容器设置脚本持续检查服务/health接口情况,当返回UP状态时,触发服务状态更新。

自动注册状态为DOWN实例配置:

spring:
  cloud:
    servicecomb:
      instance:
        initial-status: DOWN

开启优雅上下线功能配置:

spring:
  cloud:
    servicecomb:
      graceful:
        servicecombEngine:
          enabled: true

配置actuator的endpoint管理:

management:
  endpoints:
    web:
      exposure:
        include: "*"
      path-mapping:
        servicecomb-service-registry: service-registry/servicecomb

management.endpoints.web.exposure.include内容可以是"*",也可以是"health,servicecomb-service-registry"。 management.endpoints.web.path-mapping.servicecomb-service-registry配置"servicecomb-service-registry"Endpoint的调用uri。

验证是否成功,本地能够正常启动服务,且输出日志:“Endpoint ID 'servicecomb-service-registry' contains invalid characters, please migrate to a valid format.”表明配置成功。

  • 微服务K8S容器启动,以原生yaml启动为例,在K8S的postStart、preStop钩子中添加上、下线脚本,实现微服务优雅上下线

优雅上线

K8S容器post_start钩子中增加优雅上线脚本执行命令,yaml中配置内容:

spec:
  containers:
    - name: main-container
      lifecycle:
        postStart:
          exec:
            command: [
              "sh",
              "/opt/cloud/cdpipelinesvr/online.sh"   # 根据业务填写脚本路径
            ]

online.sh自动化脚本逻辑:持续检查/health接口,当/health接口返回UP时,调用定义的path-mapping路径,通知微服务注册实现优雅上线,内容如下,注意需要转化为unix格式sed -i 's/\r//' online.sh:

ip=$(ifconfig | grep 'inet' | grep -v 127.0.0.1 | awk '{print $2}')
port=8443  #服务端口号
# 定义调用微服务健康检查接口及结果处理
status_check() {
  result=$(curl -k -X GET "http://$ip:$port/health" -H "accept: application/json") #协议根据服务定http/https
  echo "${result}" | cut -c12-13 #cut截取接口返回结果result的12-13位置字符作为status_check方法的结果
}

# 循环调用健康检查接口,判断返回结果是否满足要求
status=$(status_check)
count=0
until [ "UP"x = "$status"x ]; do
  status=$(status_check)
  count=$((count + 1))
  echo "check fail, retrying ${count}"
  sleep 1
done

# 健康检查接口正确返回,调用状态更新接口将服务状态更新为‘上线’状态
curl -k -X POST http://$ip:$port/actuator/service-registry/servicecomb --header 'Content-Type: application/json' --data-raw '{"status": "UP"}'   #协议根据服务定http/https

注意:脚本仅供参考,具体实现、生效以项目适配测试为准。

优雅下线

K8S容器pre_stop钩子中增加优雅下线脚本执行命令,yaml中配置内容:

spec:
  containers:
    - name: main-container
      lifecycle:
        preStop:
          exec:
            command: [
              "sh",
              "/opt/cloud/cdpipelinesvr/offline.sh"   # 根据业务填写脚本路径
            ]

offline.sh自动化脚本如下,注意需要转化为unix格式sed -i 's/\r//' offline.sh:

ip=$(ifconfig | grep 'inet' | grep -v 127.0.0.1 | awk '{print $2}')
port=8443   # 微服务端口
curl -X POST http://$ip:$port/actuator/service-registry/servicecomb --header 'Content-Type: application/json' --data-raw '{"status": "DOWN"}'  # 此处协议根据服务自身可改为https或http
sleep 20  # 睡眠20秒

注意:脚本仅供参考,具体实现、生效以项目适配测试为准。

Nacos为注册中心场景

  • 微服务pom必须的依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
  <groupId>com.huaweicloud</groupId>
  <artifactId>spring-cloud-starter-huawei-nacos</artifactId>
</dependency>
  • 微服务开启优雅上下线配置

实现原理为:微服务启动时,关闭自动注册,此时服务无法对外提供服务,容器设置脚本持续检查服务/health接口情况,当返回UP状态时,触发服务状态更新。

关闭Nacos自动注册配置:

spring:
  cloud:
    nacos:
      discovery:
        register-enabled: false

开启优雅上下线功能:

spring:
  cloud:
    servicecomb:
      graceful:
        nacosEngine:
          enabled: true

配置actuator的endpoint管理:

management:
  endpoints:
    web:
      exposure:
        include: "*"
      path-mapping:
        nacos-service-registry: service-registry/nacos

management.endpoints.web.exposure.include内容可以是"*",也可以是"health,nacos-service-registry"。 management.endpoints.web.path-mapping.nacos-service-registry配置"nacos-service-registry"Endpoint的调用uri。

验证是否成功,本地能够正常启动服务,且输出日志:“Endpoint ID 'nacos-service-registry' contains invalid characters, please migrate to a valid format.”表明配置成功。

  • 微服务K8S容器启动,以原生yaml启动为例,在K8S的postStart、preStop钩子中添加上、下线脚本,实现微服务优雅上下线

优雅上线

K8S容器post_start钩子中增加优雅上线脚本执行命令,yaml中配置内容:

spec:
  containers:
    - name: main-container
      lifecycle:
        postStart:
          exec:
            command: [
              "sh",
              "/opt/cloud/cdpipelinesvr/online.sh"   # 根据业务填写脚本路径
            ]

online.sh自动化脚本逻辑:持续检查/health接口,当/health接口返回UP时,调用定义的path-mapping路径,通知微服务注册实现优雅上线,内容如下,注意需要转化为unix格式sed -i 's/\r//' online.sh:

ip=$(ifconfig | grep 'inet' | grep -v 127.0.0.1 | awk '{print $2}')
port=8443  #服务端口号
# 定义调用微服务健康检查接口及结果处理
status_check() {
  result=$(curl -k -X GET "http://$ip:$port/health" -H "accept: application/json") #协议根据服务定http/https
  echo "${result}" | cut -c12-13 #cut截取接口返回结果result的12-13位置字符作为status_check方法的结果
}

# 循环调用健康检查接口,判断返回结果是否满足要求
status=$(status_check)
count=0
until [ "UP"x = "$status"x ]; do
  status=$(status_check)
  count=$((count + 1))
  echo "check fail, retrying ${count}"
  sleep 1
done

# 健康检查接口正确返回,调用注册接口将服务注册到注册中心
curl -k -X POST http://$ip:$port/actuator/service-registry/nacos --header 'Content-Type: application/json' --data-raw '{"status": "UP"}'   #协议根据服务定http/https

注意: 1、11.7及以上版本配合容器的readlines检查增加注册健康检查,导致服务未完成注册时,actuator/health接口为DOWN的状态,无法作为服务是否健康判断,所以脚本中的接口需要业务自定义一个健康检查接口/health。 2、脚本仅供参考,具体实现、生效以项目适配测试为准。

优雅下线

K8S容器pre_stop钩子中增加优雅下线脚本执行命令,yaml中配置内容:

spec:
  containers:
    - name: main-container
      lifecycle:
        preStop:
          exec:
            command: [
              "sh",
              "/opt/cloud/cdpipelinesvr/offline.sh"   # 根据业务填写脚本路径
            ]

offline.sh自动化脚本内容如下,注意需要转化为unix格式sed -i 's/\r//' offline.sh:

ip=$(ifconfig | grep 'inet' | grep -v 127.0.0.1 | awk '{print $2}')
port=8443   # 微服务端口
curl -X POST http://$ip:$port/actuator/service-registry/nacos --header 'Content-Type: application/json' --data-raw '{"status": "DOWN"}'  # 此处协议根据服务自身可改为https或http
sleep 20  # 睡眠20秒

注意:文章中的自动化脚本仅供参考,具体实现、生效以项目适配测试为准。

Clone this wiki locally