实用技巧:Spring Cloud中,如何优雅下线微服务?

目录

  1. 方式一:kill java进程【不建议】
  2. 方式二:/shutdown 端点【不建议】
  3. 方式三:/pause 端点【生产可用,但有一点缺陷】
    1. 缺点&局限
  4. 方式四:/service-registry 端点【生产可用】
    1. 缺点
  5. 拓展一下

在生产环境中,服务的上下线是不可避免的,我们希望能够优雅地下线微服务。本文基于Spring Boot 2.x + Spring Cloud Finchley讲解实际项目中优雅下线服务的四种方式,并探讨各方式的优缺点。

:Spring Boot 1.x + Spring Cloud Edgware及之前的方式相同,但配置有区别,本文不做讨论。

方式一:kill java进程【不建议】

使用方式:

1
kill java进程ID

该方式借助的是Spring Boot应用的Shutdown hook,应用本身的下线也是优雅的,但如果你的服务发现组件使用的是Eureka,那么默认最长会有90秒的延迟,其他应用才会感知到该服务下线,这意味着:该实例下线后的90秒内,其他服务仍然可能调用到这个已下线的实例。因此,该方式是不够优雅的 。

方式二:/shutdown 端点【不建议】

Spring Boot提供了/shutdown 端点,可以借助它实现优雅停机。使用方式:

  • 在想下线应用的applicationyml 中添加如下配置,从而启用并暴露/shutdown 端点:

    1
    2
    3
    4
    5
    6
    7
    8
    
    management:
      endpoint:
        shutdown:
          enabled: true
      endpoints:
        web:
          exposure:
            include: shutdown
    
  • 发送POST请求到/shutdown 端点

    1
    
    curl -X http://你想停止的服务地址/actuator/shutdown
    

    该方式本质和方式一是一样的,也是借助Spring Boot应用的Shutdown hook去实现的。

方式三:/pause 端点【生产可用,但有一点缺陷】

Spring Boot应用提供了/pause 端点,利用该端点可实现优雅下线。

使用方式:

  • 在想下线应用的application.yml 中添加配置,从而启用并暴露/pause 端点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    management:
      endpoint:
        # 启用pause端点
        pause:
          enabled: true
        # 启用restart端点,之所以要启用restart端点,是因为pause端点的启用依赖restart端点的启用。详见:https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#_endpoints
        restart:
          enabled: true
      endpoints:
        web:
          exposure:
            include: pause,restart
    
  • 发送POST请求到/actuator/pause 端点:

    1
    
    curl -X POST http://你想停止的服务实例地址/actuator/pause
    
  • 执行后的效果类似下图:

    如图所示,该应用在Eureka Server上的状已被标记为DOWN ,但是应用本身其实依然是可以正常对外服务的。在Spring Cloud中,Ribbon做负载均衡时,只会负载到标记为UP 的实例上。利用这两点,你可以:先用pause端点,将要下线的应用标记为DOWN,但不去真正停止应用;然后过一定的时间(例如90秒,或者自己做个监控,看当前实例的流量变成0后)再去停止应用,例如kill 应用 ,当然如果你足够变态,kill -9 也可以 。

缺点&局限

缺点描述
不同的版本配置不大一样早期的Spring Cloud版本中,,pause端点是不依赖restart端点的,后来一个pull request导致pause端点必须依赖restart端点…个人给官方提issue,官方最后选择了继续依赖,我也是醉了……
无法和Eureka的健康检查配合使用如果你的服务发现组件用的是Eureka,并且你的应用开启了健康检查(eureka.client.healthcheck.enabled = true ,那么/pause 端点无效!!!

方式四:/service-registry 端点【生产可用】

使用方式:

  • 在想下线应用的application.yml 中添加配置,从而暴露/service-registry 端点:

    1
    2
    3
    4
    5
    
    management:
      endpoints:
        web:
          exposure:
            include: service-registry
    

    发送POST请求到/actuator/service-registry 端点:

    1
    2
    
    curl -X "POST" "http://localhost:8000/actuator/service-registry?status=DOWN" \
       -H "Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8"
    

    实行后的效果类似如下图:

    由图可知,使用/service-registry 端点可实现类似/pause 端点的效果。

缺点

暂时没有发现缺点。

拓展一下

在实际项目中,你可以做一个运维工具:

  • 运维工具读取服务发现组件中的所有服务。
  • 有一天你想下线某个服务的时候,就点击该示例的“优雅下线” 按钮,该按钮会请求到想要下线的服务的/pause 端点或者service-registry 端点(看你能不能容忍/pause 端点的缺点),这样就可以把该实例在Eureka上标记为DOWN,流量过一段时间后就不会打到这个实例上。
  • 做一个流量检测工具(例如QPS统计,这种百度随便找下,最简单的一个过滤器 + map就可以做了),如果检测到当前实例确实已经没有流量进入,就在运维工具上点击另一个按钮,例如停止。真正停止应用。
    • 当然,如何停止应用又是另一个问题了,例如你可以请求实例的shutdown端点(Spring Boot提供了优雅下线的端点),或者用脚本kill,或者如果是容器可以借助一些探针……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值