对于任何一个线上应用,由于重启、下线等操作不可避免,无损下线能够实现服务消费者无感知,保持业务连续无损。您无需对应用进行任何配置、也无需在 EDAS 控制台进行任何操作,EDAS 默认支持 Spring Cloud 应用无损下线。

为什么需要无损下线

如何保证从应用停止到恢复服务期间不影响正常运行的消费者的业务请求?理想条件下,在整个服务没有请求的时候再进行更新是安全可靠的。但实际情况下,无法保证在服务下线的同时没有任何调用请求。

传统的解决方式是通过将应用更新流程划分为手工摘除流量、停应用、更新重启三个步骤,由人工操作实现客户端对更新无感知。

如果在容器/框架级别提供某种自动化机制,自动进行摘除流量并确保处理完已到达的请求,不仅能保证业务不受更新影响,还可以极大地提升更新应用时的运维效率。这个机制就是无损下线。

EDAS 无损下线的优势

开源 Spring Cloud 可以通过 shutdownHook、Spring Boot Actuator 和 Ribbon 实现,不仅有一定的开发工作量,而且最终还会由于注册中心,导致流量损失。

EDAS 将无损下线的流程整合在发布流程中,对应用进行停止、部署、回滚、缩容、重置等操作时,无损下线会自动执行。相对于开源的方案,EDAS 无损下线具有以下优势:

分类 开源 Spring Cloud EDAS
版本 使用 ServiceRegistryEndpoint,需要依赖Actuator 组件,且需要升级到适配的版本。 无需任何操作,无侵入地支持 Spring Cloud Dalston 及以上版本。
注册中心和流量损失 依赖注册中心,有些注册中心会导致流量损失。
  • ZooKeeper 不存在流量损失
  • Eureka 存在 3s 流量损失
  • Nacos 存在客户端缓存,流量最大可能损失 10s。
无需依赖任何注册中心,对于任何注册均不存在流量损失。
场景 ECS 场景需要结合变更详情;K8s 场景可以配合 prestop 接口,但是 prestop 接口只能配置一个动作。 ECS 和 K8s 全部覆盖, 且不影响对应用的任何操作与配置。
客户端缓存 需要权衡利弊配置合理的 Ribbon 缓存的刷新时间,过长会导致下线有流量损失,过短会影响性能。 增强 Netflix Ribbon 下线刷新机制,通过反应式响应方式主动刷新 Ribbon 缓存。您无需关心。

如何验证无损下线是否生效

您可以直接根据实际业务验证应用的无损下线是否已经生效。另外,EDAS 也提供了两个应用 Demo,您可以使用这两个 Demo 在容器服务 K8s 集群中验证 EDAS 的无损下线。

无损下线验证流程如下:

  1. 下载应用 Demo(ProviderConsumer)。
  2. 将应用 Demo 部署到容器服务 K8s 集群。
    其中,Provider 的实例个数为 2,Consumer 的实例个数为 1。部署的详细操作步骤,请参见应用部署概述(K8s 集群)
    部署应用
  3. 查看应用调用现状。
    1. 登录部署 Consumer 的 Pod,执行以下命令不停地访问服务端的服务。
      #!/usr/bin/env bash
      while true
      do
          echo `curl -s -XGET http://localhost:18091/user/rest`
      done
    2. 查看调用请求的响应。
      正常调用结果

      从响应中可以看到, Consumer 随机访问 Provider 的两个实例(IP 为 172.20.0.221 和 172.20.0.223)。

      注意 调用请求的响应窗口不要关闭,后续仍然会用到。
  4. 将 Provider 的实例缩容到 1,模拟实例重启的场景。详情请参见扩容和缩容应用(容器服务 Kubernetes 集群)
  5. 再次查看调用请求的响应结果,验证无损下线。
    调用请求响应-无损下线

    一直观察客户端请求情况,可以看到"无损"下线的情况,同时观察客户端日志,不存在任何相关问题,客户端完全无感知。

    从响应中可以看到, Consumer 会固定访问 Provider 剩余的一个实例(IP 为 172.20.0.221),而不会发生调用异常,影响 Consumer。