Serverless 架构下的服务优雅下线实践


应用发布、服务升级一直是一个让开发和运维同学既兴奋又担心的事情 。
兴奋的是有新功能上线 , 自己的产品可以对用户提供更多的能力和价值;担心的是上线的过程会不会出现意外情况影响业务的稳定性 。 确实 , 在应用发布和服务升级时 , 线上问题出现的可能性更高 , 本文我们将结合 Serverless 应用引擎(以下简称 SAE)就 Serverless 架构下 , 讨论如何保障上线过程中服务的优雅下线 。
在平时的发布过程中 , 我们是否遇到过以下问题:

  • 发布过程中 , 出现正在执行的请求被中断?
  • 下游服务节点已经下线 , 上游依然继续调用已经下线的节点导致请求报错 , 进而导致业务异常?
  • 发布过程造成数据不一致 , 需要对脏数据进行修复 。
有时候 , 我们把发版安排在凌晨两三点 , 赶在业务流量比较小的时候 , 心惊胆颤、睡眠不足、苦不可言 。 那如何解决上面的问题 , 如何保证应用发布过程稳定、高效 , 保证业务无损呢?首先 , 我们来梳理下造成这些问题的原因 。
场景分析
Serverless 架构下的服务优雅下线实践
本文插图
这个图描述了我们使用微服务架构开发应用的一个常见的场景 , 先看下这个场景的服务调用关系:
  • 服务 B、C 把服务注册到服务注册中心 , 服务 A、B 从注册中心发现依赖的服务 。
  • 业务流量从负载均衡路由到服务 A , 在 SLB 上配置服务 A 实例的健康检查 , 当服务 A 有实例停机的时候 , 相应的实例从 SLB 摘掉;服务 A 调用服务 B , 服务B再调用服务C 。
【Serverless 架构下的服务优雅下线实践】从图中 , 可以看到有两类流量 , 南北向流量(即通过 SLB 转发到后端服务器的业务流量 , 如业务流量->SLB->A的调用链路)和东西向流量(借助于服务注册中心服务发现调用的流量 , 如服务A->服务B的调用链路)
针对这两类流量我们分别进行分析 。 先来分析下在这种架构下南北向流量存在的问题 , 当服务 A 发布的时候 , 服务A1 实例停机后 , SLB 根据健康检查探测到实例 A1 下线 , 然后把实例从 SLB 摘掉 , 实例 A1 依赖 SLB 的健康检查从 SLB 上摘掉 , 一般需要几秒到十几秒的时间 , 在这个过程中 , 如果 SLB 有持续的流量打入 , 就会造成一些请求继续路由到实例 A1 , 导致请求失败 。
那如何保证经过SLB的业务流量不报错?我们看下 SAE 是如何做到的 。
南北向流量优雅下线方案
Serverless 架构下的服务优雅下线实践
本文插图
上面提到过 , 请求失败的原因在于后端服务实例先停止掉 , 然后才从 SLB 摘掉 , 那我们是不是可以先从 SLB 摘掉服务实例 , 然后在对实例进行升级呢?
按照这个思路 , SAE 基于 K8s Service 的能力给出了一种方案 , 当用户在通过 SAE 为应用绑定 SLB 时 , SAE 会在集群中创建一个 Service 资源 , 并把应用的实例和 Service 关联 , CCM 组件会负责 SLB 的购买、SLB 虚拟服务器组的创建 , 并且把应用实例关联的 ENI 网卡添加到虚拟服务器组中 , 从而用户可以通过 SLB 来访问应用实例;当应用发布时 , CCM 组件会先把实例对应的 ENI 从虚拟服务器组中摘除 , 然后再对实例进行升级 , 从而保证了流量不丢失 。
东西向流量优雅下线方案
在讨论完南北向流量的解决方案后 , 我们再看下东西向流量 ,传统的发布流程中 , 服务提供者停止再启动 , 服务消费者感知到服务提供者节点停止的流程如下:
Serverless 架构下的服务优雅下线实践
本文插图


推荐阅读