概述

对大多数互联网利用来说,利用是没有状态的,所以不停服更新绝对较容易实现,咱们有十分多带状态服务,这里对不停服更新的实现做一些记录。

实现拆解

残缺启动

在停机更新时,此组件凋谢的粒度是整个平台,不停服更新时,凋谢的粒度是单个组件过程,组件对外之前,必须确保外部曾经初始化结束。

K8S探针

K8S定义了一些探针,其中和不停服相干的,次要是就绪探针,和启动探针,它们定义了利用在什么时候算是筹备好(业务流量什么时候进入节点):

  • 就绪探针 (Readiness),循环调用,决定服务发现,有没有流量进来(包含INGRESS和DNS,DNS简直是实时的,当节点滚动更新开始后,到节点就绪探针返回胜利前,DNS无奈发现对应节点,揣测INGRESS也是依赖DNS,所以,同样部署在K8S上的HTTP服务不须要额定减少SLB)。
  • 存活探针 (Liveness),循环调用,失败重启容器。
  • 启动探针 (Startup),先于就绪和存活探针调用,只胜利调用一次,能够用于预热。

erlang过程启动、敞开程序梳理

  • 留神启动、敞开程序,让外部服务先开启,入口后(如对外端口开启,服务发现注册)开启,被依赖项先于依赖项启动。
  • 如果应用异步加载,能够应用K8S Startup 探针。

优雅敞开

http短连贯优雅敞开

节点敞开时,DNS会马上移除,思考在途包,stop脚本须要sleep一小段时间(5秒)。
nginx 能够设置一个等待时间。

worker_shutdown_timeout 10;

服务发现优雅敞开

参考启动,敞开程序是:

  1. 摘除服务注册信息。
  2. 期待在途包隐没加一小段时间。

长连贯优雅敞开

长连贯是状态的一种,须要解决流量切换。

切流控制命令字

断开参考了HTTP2的GOAWAY指令。
至多有两条对等的通道,在连贯敞开时,用其它连贯进行调用。

一个失常的敞开流程:

sequenceDiagram    server->>+server: 进行端口监听,防止有新连贯创立。    server->>+client1: RPC1    client1->>+server: RPC1 RESP    server->>+server: 确保己方所有连贯不再有扇出的新申请,一一发送GOAWAY。    server->>+client1: GOAWAY    server->>+client2: GOAWAY    client1->>client1: 切流    client1->>server: GOAWAY    server->>+server: client1连贯曾经发送&接管GOAWAY,能够马上敞开。    server->>+server: 期待己方所有连贯断开,尽管client2连贯未断开,在一段时间后强制敞开利用。

留神不能应用TCP半敞开,在一方敞开申请后,还可能须要回复返回包。

服务发现接口

只有接入了切流控制命令字,无需接入服务发现接口,也能够做到长连贯优雅敞开。

服务发现接口有助于:

  1. 负载平衡。
  2. 容灾,能够疾速摘除故障节点。

用k8s原生的dns是能够通过轮询感知节点变动的,因为咱们还有swarm部署形式,故用etcd实现了相似于k8s endpoints 的 long pooling 服务发现接口:

状态迁徙

对有状态的节点,须要多做一些解决:在敞开前,须要先将状态迁徙走。
此前我实现了一个有核心节点治理的一致性哈希集群库,提供了申明式的rebalance_cluster接口:

rebalance_cluster("cluster1", ["node1", "node2"])

这里参考了K8S的节点状态,核心思想是:让利用上报本人的状态到核心节点,让核心节点用rebalance_cluster接口摘除下线(terminating)节点,并将running节点主动退出到集群中。对长时间不上报的节点,认为是unknown状态,会做摘除解决。

长时间运行工作

视工作运行时常而定,能够抉择:

  • 期待工作执行结束,须要关注节点最大退出工夫。
  • 将大工作拆分成小工作,写入外存,分而治之。

其它

erlang的热更为什么不行?
erlang的application-upgrade-file的粒度过小了。以一个简略的无状态组件为例,如果用K8S做热更新,程序员心智累赘较小,只须要放弃接口、数据向前兼容,就能够将节点灰度上线。而erlang的application-upgrade-file,程序员要思考load module的程序,操纵内存数据等,心智累赘显著更大。
当然erlang application-upgrade-file做在线hot fix还是很适合的。

总结

这里对前段时间所做的不停服更新专项的次要思维做了一些总结。理论落地的状况比本文总结的要简约一些,这里就不探讨细节了。
不停服更新,技术上不难,难的是放弃外部接口、数据的兼容性。在外部接口、数据放弃兼容的状况下,咱们能够应用不停服更新,从而升高停服更新的频率。

参考

  • https://kubernetes.io/docs/concepts/services-networking/servi...
  • https://datatracker.ietf.org/doc/html/rfc7540#section-6.8
  • https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecy...
  • https://www.erlang.org/doc/design_principles/release_handling...