其他
Serverless 架构下的服务优雅下线实践
责编 | 晋兆雨
发布过程中,出现正在执行的请求被中断? 下游服务节点已经下线,上游依然继续调用已经下线的节点导致请求报错,进而导致业务异常? 发布过程造成数据不一致,需要对脏数据进行修复。
场景分析
服务 B、C 把服务注册到服务注册中心,服务 A、B 从注册中心发现依赖的服务。 业务流量从负载均衡路由到服务 A,在 SLB 上配置服务 A 实例的健康检查,当服务 A 有实例停机的时候,相应的实例从 SLB 摘掉;服务 A 调用服务 B,服务B再调用服务C。
南北向流量优雅下线方案
上面提到过,请求失败的原因在于后端服务实例先停止掉,然后才从 SLB 摘掉,那我们是不是可以先从 SLB 摘掉服务实例,然后在对实例进行升级呢?
东西向流量优雅下线方案
服务发布前,消费者根据负载均衡规则调用服务提供者,业务正常。 服务提供者 B 需要发布新版本,先对其中的一个节点进行操作,首先是停止 Java 进程。 服务停止过程,又分为主动注销和被动注销,主动注销是准实时的,被动注销的时间由不同的注册中心决定,最差的情况会需要 1 分钟。
如果应用是正常停止,Spring Cloud 和 Dubbo 框架的 Shutdown Hook 能正常被执行,这一步的耗时可以忽略不计。 如果应用是非正常停止,比如直接使用 kill -9 停止,或者 Docker 镜像构建的时候 Java 应用不是 1 号进程且没有把 kill 信号传递给应用。那么服务提供者不会主动去注销服务节点,而是在超过一段时间后由于心跳超时而被动地被注册中心摘除。 服务注册中心通知消费者,其中的一个服务提供者节点已下线。包含推送和轮询两种方式,推送可以认为是准实时的,轮询的耗时由服务消费者轮询间隔决定,最差的情况下需要 1 分钟。 服务消费者刷新服务列表,感知到服务提供者已经下线了一个节点,这一步对于 Dubbo 框架来说不存在,但是 Spring Cloud 的负载均衡组件 Ribbon 默认的刷新时间是 30 秒 ,最差情况下需要耗时 30 秒。 服务消费者不再调用已经下线的节点。
服务提供者应用在发布前后主动向注册中心注销应用,并将应用标记为已下线的状态;将原来的停止进程阶段 注销服务变成了 prestop 阶段注销服务。 在接收到服务消费者请求时,首先会正常处理本次调用,并通知服务消费者此节点已下线,服务消费者会立即从调用列表删除此节点;在这之后,服务消费者不再调用已经下线的节点。这是将原来的依赖于 注册中心推送,变成了服务提供者直接通知消费者从调用列表中摘除自己。
分批发布和灰度发布
更多阅读推荐