共计 2223 个字符,预计需要花费 6 分钟才能阅读完成。
概述
对大多数互联网利用来说,利用是没有状态的,所以不停服更新绝对较容易实现,咱们有十分多带状态服务,这里对不停服更新的实现做一些记录。
实现拆解
残缺启动
在停机更新时,此组件凋谢的粒度是整个平台,不停服更新时,凋谢的粒度是单个组件过程,组件对外之前,必须确保外部曾经初始化结束。
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;
服务发现优雅敞开
参考启动,敞开程序是:
- 摘除服务注册信息。
- 期待在途包隐没加一小段时间。
长连贯优雅敞开
长连贯是状态的一种,须要解决流量切换。
切流控制命令字
断开参考了 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 半敞开,在一方敞开申请后,还可能须要回复返回包。
服务发现接口
只有接入了切流控制命令字,无需接入服务发现接口,也能够做到长连贯优雅敞开。
服务发现接口有助于:
- 负载平衡。
- 容灾,能够疾速摘除故障节点。
用 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…