🔥Serverless 微服务优雅关机实践| 🏆 技术专题第七期征文

应对业务服务的发布和服务升级时,线上出现问题的可能性很高,就 Serverless 架构下讨论如何保障上线过程当中服务的优雅下线java

Solomon_肖哥弹架构 跟你们“弹弹” 如何更加优雅的进行服务下线,贯穿南北与东西流量的调度方案。后端

平时发布过程否遇到如下问题:服务器

  • 发布过程当中,出现正在执行的请求被中断
  • 下游服务节点已经下线,上游依然继续调用已经下线的节点致使请求报错,进而致使业务异常
  • 发布过程形成数据不一致,须要对脏数据进行修复。

一般发版安排在凌晨两三点,在业务流量比较小的时候。那如何解决上面的问题,如何保证应用发布过程稳定、高效,保证业务无损。markdown

场景分析

上图描述了咱们使用微服务架构开发应用的一个常见场景,咱们先看下这个场景的服务调用关系:架构

  • 服务 B、C 把服务注册到注册中心,服务 A、B 从注册中心发现须要调用的服务;
  • 业务流量从负载均衡打到服务 A,在 SLB 上配置服务 A 实例的健康检查,当服务 A 有实例停机的时候,相应的实例从 SLB 摘掉;服务 A 调用服务 B,服务 B 再调用服务 C;

上图有两类流量app

  • 南北向流量:
    • 即经过 SLB 转发到后端服务器的业务流量,如业务流量 -> SLB -> A 的调用路径
  • 东西向流量:
    • 经过注册中心服务中心服务发现来调用的流量,如 A -> B 的调用路径

南北向流量

南北向流量问题

当服务 A 发布的时候,服务 A1 实例停机后,SLB 根据健康检查探测到服务 A1 下线,而后把实例从 SLB 摘掉。实例 A1 依赖 SLB 的健康检查从 SLB 上摘掉,通常须要几秒到十几秒的时间,在这个过程当中,若是 SLB 有持续的流量打入,就会形成一些请求继续路由到实例 A1,致使请求失败;负载均衡

服务 A 在发布的过程当中,如何保证通过 SLB 的流量不报错?咱们接着看下 SAE 是如何作的。框架

南北向流量优雅升级方案

请求失败的缘由在于后端服务实例先中止掉,而后才从 SLB 摘掉,那咱们是否是能够先从 SLB 摘掉服务实例,而后再对实例进行升级呢?less

按照这个思路,SAE 基于 K8S service 的能力给出了一种方案微服务

  • 当用户在经过 SAE 为应用绑定 SLB 时,SAE 会在集群中建立一个 service 资源,并把应用的实例和 service 关联,CCM 组件会负责 SLB 的购买、SLB 虚拟服务器组的建立,而且把应用实例关联的 ENI 网卡添加到虚拟服务器组中,用户能够经过 SLB 来访问应用实例;
  • 当应用发布时,CCM 会先把实例对应的 ENI 从虚拟服务器组中摘除,而后再对实例进行升级,从而保证流量不丢失。

这就是 SAE 对于应用升级过程当中关于南北向流量的保障方案。

东西向流量

东西向流量问题

在传统的发布流程中,服务提供者中止再启动,服务消费者感知到服务提供者节点中止的流程以下:

  1. 服务发布前,消费者根据负载均衡规则调用服务提供者,业务正常。
  2. 服务提供者 B 须要发布新版本,先对其中的一个节点进行操做,首先是中止 java 进程。
  3. 服务中止过程,又分为主动注销和被动注销,主动注销是准实时的,被动注销的时间由不一样的注册中心决定,最差的状况会须要 1 分钟。
    • 若是应用是正常中止,Spring Cloud 和 Dubbo 框架的 Shutdown Hook 能正常被执行,这一步的耗时能够忽略不计。
    • 若是应用是非正常中止,好比直接使用 kill -9 中止,或者 Docker 镜像构建的时候 java 应用不是 1 号进程且没有把 kill 信号传递给应用。那么服务提供者不会主动去注销服务节点,而是在超过一段时间后因为心跳超时而被动地被注册中心摘除。
  4. 服务注册中心通知消费者,其中的一个服务提供者节点已下线。包含推送和轮询两种方式,推送能够认为是准实时的,轮询的耗时由服务消费者轮询间隔决定,最差的状况下须要 1 分钟。
  5. 服务消费者刷新服务列表,感知到服务提供者已经下线了一个节点,这一步对于 Dubbo 框架来讲不存在,可是 Spring Cloud 的负载均衡组件 Ribbon 默认的刷新时间是 30 秒 ,最差状况下须要耗时 30 秒。
  6. 服务消费者再也不调用已经下线的节点。

从第 2 步到第 6 步的过程当中,Eureka 在最差的状况下须要耗时 2 分钟,Nacos 在最差的状况下须要耗时 50 秒。在这段时间内,请求都有可能出现问题,因此发布时会出现各类报错,同时还影响用户的体验,发布后又须要修复执行到一半的脏数据。最后不得不每次发版都安排在凌晨两三点发布,心惊胆颤,睡眠不足,苦不堪言。

东西向流量优雅升级方案

在传统发布流程中,客户端有一个服务调用报错期,缘由就是客户端没有及时感知到服务端下线的实例。在传统发布流程中,主要是借助注册中心通知消费者来更新服务提供者列表,那能不能绕过注册中心,服务提供者直接通知服务消费者呢?答案是确定的,咱们主要作了两件事情:

  • 服务提供者应用在发布先后主动向注册中心注销应用,并将应用标记为已下线的状态;将原来的中止进程阶段注销服务变成了 prestop 阶段注销服务。
  • 在接收到服务消费者请求时,首先会正常处理本次调用,并通知服务消费者此节点已下线,服务消费者会当即从调用列表删除此节点;在这以后,服务消费者再也不调用已经下线的节点。这是将原来的依赖于 注册中心推送,作到了服务提供者直接通知消费者从调用列表中摘除本身。

经过上面这个方案,就使得下线感知的时间大大减短,从原来的分钟级别作到准实时,确保应用在下线时能作到业务无损。

分批发布和灰度发布

上文介绍的是 SAE 在处理优雅下线方面的一些能力,在应用升级的过程当中,只有实例的优雅下线是不够的,还须要有一套配套的发布策略,保证咱们新业务是可用的,SAE 提供分批发布和灰度发布的能力,可使得应用的发布过程更加省心省力;

咱们先介绍下灰度发布,某应用包含 10 个应用实例,每一个应用实例的部署版本为 Ver.1 版本,现需将每一个应用实例升级为 Ver.2 版本。

从图中能够看出,在发布的过程当中先灰度 2 台实例,在确认业务正常后,再分批发布剩余的实例,发布的过程当中始终有实例处于运行状态,实例升级过程当中依照上面的方案,每一个实例都有优雅下线的过程,这就保证了业务无损。

再来看下分批发布,分批发布支持手动、自动分批;仍是上面的 10 个应用实例,假设将全部应用实例分 3 批进行部署,根据分批发布策略,该发布流程如图所示,就再也不具体介绍了。

你的点赞关注Solomon_肖哥弹架构持续的动力。

🏆 技术专题第七期 |万物皆可 Serverless

相关文章
相关标签/搜索