斗鱼基于etcd和ZooKeeper的注册中心实践案例

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第1张图片

业务背景和痛点

9eecf3e1f5fe37ed2360e6780391e9bc.png

斗鱼直播作为业界领先的游戏直播平台,每天为数以亿计的互联网用户提供优质的游戏直播观看、互动和娱乐等服务。

随着近年直播市场的火热,斗鱼直播平台作为业内口碑和体验俱佳的互联网公司,用户量也出现井喷式增长。海量用户给平台带来的稳定性技术挑战也越发强烈,斗鱼的老架构如下图所示,无论是业务支撑还是架构设计,均存在一定的风险和隐患。

斗鱼老架构

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第2张图片

图一 斗鱼老架构

为了给用户带来更好的可用性体验,斗鱼急需解决单一数据中心的问题,将老架构从单数据中心升级到多数据中心。

多数据中心挑战

在实现单活升级为多活的过程中,为了确保无故障的迁移升级,我们面临一系列挑战,比如:

  • 有状态服务 etcd、ZooKeeper 等如何多数据中心同步?

  • 应用彼此之间存在 1 个复杂的树状或网状依赖关系,应该从哪里开始迁移?

  • 按什么维度来划分目标的边界,怎么避免业务焊死在一起,造成无从下手的局面?

  • 如果迁移后出现问题,如何快速恢复,并且不牵连已迁移成功的业务?

因单活升级到多活的过程中,涉及系统众多,本文将是斗鱼直播多活改造系列的第一篇,只聚焦于注册中心模块,因此我们先和你介绍下注册中心背后的 etcd 和 ZooKeeper。

ZooKeeper/etcd 承担的角色

Dubbo 通过注册中心来解决大规模集群下的服务注册与发现问题,以下是注册中心架构图:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第3张图片

Dubbo 默认支持 ZooKeeper 注册中心,虽然新版也有 etcd 实现,但该实现尚缺乏大规模投产的先例,Java 技术栈采用 etcd 作为注册中心的案例也比较罕见。

当采用 ZooKeeper 作为 Dubbo 注册中心时,其注册关系为树形结构,详细结构如下图所示:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第4张图片

因为 ZooKeeper 是基于类似文件系统的树形结构来存储数据,但 etcd 却是采用键值对存储,二者之间的差异会给注册关系同步带来较大困难。

此外,如果从 ZooKeeper 迁移到 etcd,则在整个迁移过程中:已有的线上服务不能受损,更不能停服;如果迁移失败,还要能回退到 ZooKeeper。

同城双活与多活新架构

为了实现多活,我们通过跨数据中心的同步服务、服务依赖梳理与边界划分、可控变更等技术手段和运维理念,成功解决了以上挑战,设计了如下一套新的架构来实现多活,如下图所示:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第5张图片

图二 斗鱼多活新架构

在新的架构下,可以按域名甚至是 URL 来细粒度的调度流量,RPC 层面也具备了自动就近调用的能力,其中注册中心的局部架构图如下:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第6张图片

图三 斗鱼注册中心老架构

注册中心多活方案选型与目标

在注册中心多活改造过程中,我们面临多个方案,如下表所示:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第7张图片

由于历史原因,我们有 ZooKeeper(以下简称 zk)和 etcd 这 2 套注册中心,加上我们有 Java、Go、C++、PHP 这 4 个技术栈,因此在注册中心领域仍然有一些不足,希望能统一到 etcd 来解决痛点问题,并达到以下目标:

降低维护成本:此前需要运维 zk + etcd 两套注册中心,更困难的是做多活解决方案时也需要适配 zk + etcd,这导致注册中心多活研发成本翻倍。由于 etcd 是 Kubernetes 的一部分,运维 etcd 又不可避免,这是选择 etcd 的第 1 个原因。

拥抱更繁荣的生态:etcd 有云原生托管解决方案,有厂商通过 etcd 管理 10K Node 级别的 Kubernetes 集群,etcd 还自带 proxy、cache、mirror 等各种周边工具,Java 侧 Dubbo 也支持以 etcd 作为注册中心,etcd 相对于 zk 来说发展前景更好,这是选择 etcd 的第 2 个原因。

增强跨语言能力:etcd 可基于 http 或 gRPC 协议通讯,并且支持长轮询,具有较强的跨语言能力。而 zk 需要引入专用客户端,除 java 客户端之外,其它语言客户端尚不成熟。而我们有 Java、Go、C++、PHP 等 4 种研发语言,这是选择 etcd 的第 3 个原因。

基于以上原因,我们选择了方案四,方案四大新架构如下图所示:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第8张图片

图四 斗鱼注册中心新架构

注册中心多活难点与挑战

为了实现新注册中心,达到我们期望的设计目标,注册中心在改造过程中,面临以下难点与挑战:

  • 如何解决 zk 的多数据中心同步问题?尤其是 zookeeper watch 机制是不可靠的,可能出现丢失 watch 事件的问题?(正确性)

  • 如何解决 etcd 的多数据中心同步问题?从下面方案选型中,我们可以看到社区目前并无任何成熟、生产环境可用的解决方案。(正确性)

  • 如何解决跨数据中心读的性能问题?(性能)

  • 如何解决跨数据中心的服务稳定性问题?网络链路上,比如内网专线若中断了怎么办?同步服务设计上,是否会导致 etcd/zk 同步服务进入性能极慢的全同步逻辑,同步服务本身是否具备高可用等等?容灾测试上,我们又该如何设计测试用例验证?运维上,我们又该如何快速发现隐患、消除潜在的故障,建设可视化、灵活的多活运维系统?(稳定性、可运维性)

注册中心多活难点分析

1f68fa8f97a6d8db940b3f4cd493c5b8.png

迁移过程中如何保证新旧服务互通?

开发 zk2etcd

我们很多 Java 开发的业务使用 Dubbo 框架做服务治理,注册中心是 ZooKeeper,我们希望 Java 和 Go 开发的业务全部都统一使用 etcd 作为注册中心,也为跨语言调用的可能性做好铺垫。

由于业务众多,改造和迁移的周期会很长,预计持续 1~2 年,在此过程中我们需要将 zookeeper 中的注册数据同步到 etcd 中,实时同步,而且要保证数据一致性以及高可用,当前市面上没有找到满足我们需求的工具,于是我们和腾讯云 TKE 团队合作开发了一个 zk2etcd 来同步实现 ZooKeeper 数据到 etcd,并且已将其开源,整体方案落地篇我们将详细介绍。

如何实现 etcd 异地容灾?

通过 zk2etcd 同步服务,我们成功解决了 ZooKeeper 数据迁移问题,使得新老业务的注册中心数据都使用 etcd 来存储。

因此,etcd 的重要性不言而喻,它的可用性决定着我们的整体可用性,而斗鱼直播目前的部署架构又严重依赖某核心机房,一旦核心机房出现故障,将导致整体不可用。因此斗鱼直播下一个痛点就是提升 etcd 的可用性,期望实现 etcd 跨城容灾、异地容灾能力。

斗鱼直播理想中的 etcd 跨城同步服务应该具备如下特性:

  • etcd 跨城容灾部署后,读写性能不显著下降,能满足业务场景基本诉求。

  • 同步组件达到生产环境可用级别,具备完备的一致性检测、日志、Metrics 监控等。

  • 对数据一致性要求不强的业务可就近访问同地区的 etcd 集群服务、强一致诉求业务可访问主 etcd 集群。

  • 主集群故障后,业务运维能根据一致性监控等,快速将备集群提升为主集群。

那么有哪些方案呢?各个方案又有哪些优缺点呢?最终评估了如下几种方案:

  • 单集群多地部署方案

  • etcd 社区 make-mirror 方案

  • etcd 社区 learner 方案

  • 腾讯云 etcd-syncer 方案

单集群多地部署方案

单集群多地部署方案图如下:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第9张图片

在此方案中,etcd Leader 节点通过 Raft 协议将数据复制到各个地域的 Follower 节点。

此方案它的优点如下:

  • 各地域网络互通后,部署简单,无需运维额外组件

  • 数据跨城强一致同步,3 节点部署场景中,可容忍任一城市故障,并且不丢失任何数据

介绍完它的优点后,我们再看看它的缺点,如下所示:

  • 在 3 节点部署的场景下,任意写请求至少需要两个节点应答确认,而不同节点部署在各地,ping 延时会从几毫秒上升到 30ms 左右(深圳 - 上海),因此会导致写性能急剧下降。

  • etcd 默认的读请求是线性读,当 Follower 节点收到 Client 发起的读请求后,它也需要向 Leader 节点获取相关信息,确认本地数据追赶上 Leader 后才能返回数据给 client,避免读取到旧数据等,在这过程中也会导致 etcd 读延时上升、吞吐量下降。

  • 跨城部署网络之间质量也较容易波动,导致服务质量抖动等。

  • client 访问 etcd 集群的配置,为了防止单点故障,必须配置多个 etcd 节点,而这又可能导致 client 访问到异地的 etcd 节点,导致服务请求延时增大等。

etcd 社区 make-mirror 方案

介绍完单集群多地部署方案后,我们再看看 etcd 社区提供的 make-mirror 方案,它的原理图如下:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第10张图片

在此方案中,我们分别在不同城市部署了一套独立的 etcd 集群,通过 etcd 社区提供的 make-mirror 工具实现跨城数据复制。

make-mirror 工具原理如下:

  • 指定数据同步的前缀后,通过 etcd Range 读接口从主集群遍历此前缀下的所有数据,写入到目的 etcd。(全量同步)

  • 随后通过 etcd Watch 接口指定读请求返回的“版本号”,监听从此版本号后的所有变更事件。

  • make-mirror 收到主 etcd 集群推送的 key-value 变化事件后,通过 txn 事务接口将数据写入到热备集群。(增量同步)

此方案它的优点如下:

  • 主 etcd 集群读写性能高,整体上不受跨地域网络延时、网络质量波动影响

  • 若业务可容忍短暂不一致,可就近访问距离最近的 etcd 集群

  • 若业务要求强一致,可通过内网专线访问主 etcd 集群

  • 不依赖高版本 etcd

介绍完它的优点后,我们再看看它的缺点,如下所示:

  • 当写请求较大的时候,备集群可能存在一定的数据落后,可能读到脏数据。

  • 社区自带的 make-mirror 同步链路中断后,退出重启会再次进入全量同步模式,性能较差,无法满足生产环境诉求。

  • 社区自带的 make-mirror 工具缺少 leader 选举、数据一致性检测、日志、Metrics 等一系列特性,不具备生产环境可用性。

  • 不支持同步非 key-value 数据,如 auth 鉴权相关数据、lease 数据等。

etcd 社区 Learner 方案

介绍完 etcd 社区的 make-mirror 方案后,我们再看看 etcd 社区提供的 learner 方案,它的原理图如下:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第11张图片

它的核心原理如下:

  • etcd raft 算法库在 2017 年的时候就已经支持了 Learner 节点,详情可参考 pr 8751。

  • etcd 社区在 2019.8 月推出的 3.4 版本中,正式支持 Learner 节点,它作为非投票(Non-Voting)的成员节点加入集群,不参与集群选举等投票,只进行数据复制。

  • Leader 收到写请求后,将日志同步给 Follower 和 Learner 节点,并在内存中使用一个名为 Progress 的数据结构,维护 Follower 和 Learner 节点的日志同步进展信息。

  • 当 Learner 节点的数据与 Leader 数据差距较小的时候,它就可以被提升为可投票的成员节点加入集群。

此方案它的优点如下:

  • 各地域网络互通后,部署简单,只需往 etcd 集群中添加一个 Learner 节点,无需运维额外组件

  • Learner 节点可同步任意类型数据,如 key-value、auth 鉴权数据、lease 数据

介绍完它的优点后,我们再看看它的缺点,如下所示:

  • Learner 节点只允许串行读,也就是业务如果就近读,会读到旧数据。

  • 依赖高版本 etcd,etcd 3.4 及以上版本才支持 Learner 特性,并且只允许一个 Learner 节点。

  • 主集群全面故障后,无法快速将 Learner 节点提升为可写的独立 etcd 集群。

介绍完已有的几种方案后,我们发现它们都无法满足业务生产环境诉求,于是我们自研完成了生产环境可用的 etcd 同步服务落地,在整体方案落地章节将详细介绍。

如何确保 etcd 和 ZooKeeper 同步服务的稳定性、可运维性?

为了确保 etcd、ZooKeeper 同步服务的稳定性,模拟 5 类常见的故障,检验服务在这些典型故障场景下的自愈能力,详细测试方案如下。

故障场景

  1. Redis 闪断(zk2etcd 服务依赖),例如:Redis 版本升级、非平滑扩容。

  2. zk2etcd 离线,例如:OOM、容器驱逐、宿主机故障。

    斗鱼基于etcd和ZooKeeper的注册中心实践案例_第12张图片

  3. etcd2etcd 离线 ,例如:OOM、容器驱逐、宿主机故障

  4. 网络闪断,例如:OOM、容器驱逐、宿主机故障。

  5. 弱网环境,例如:专线断掉后临时用公网顶替。

上述 5 种场景的实际触发原因有多种多样,只需要模拟出一种情况。

演练方案

  1. Redis 闪断:通过改 host 模拟 Redis 不可达,此时自动订正停止;模拟 Redis 恢复后,自动订正亦自动恢复。

  2. zk2etcd 离线:通过杀容器节点模拟 zk2etcd 挂掉,15 秒内 Kubernetes 自动拉起,拉起完成后同步正常、数据一致。

  3. etcd2etcd 离线:通过杀容器节点模拟 zk2etcd 挂掉,15 秒内 Kubernetes 自动拉起,拉起完成后同步正常、数据一致。

  4. 网络闪断:通过改 host 模拟 ZooKeeper、etcd 不可达,此时同步中断,后去掉 host 模拟网络恢复,恢复后同步正常、数据一致。

  5. 弱网环境:通过切公网模拟弱网环境,切公网后同步效率降低在 4 倍以内,1 次全量同步仍然可在 1 分钟内完成。

另外针对可运维性问题,无论是 etcd 还是 ZooKeeper 同步服务,都提供了详细的 Metrics、日志,我们针对各个核心场景、异常场景都配置了可视化的观测视图,并配置了告警策略。

整体方案落地

6e23922a8189fb990db26fa0aec0fafc.png

整体架构

etcd 集群多活架构图如下所示:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第13张图片

说明:

  • 黑实线:正常情况下的专线访问

  • 黑虚线:切公网方式访问

  • 红实线:etcd 集群发生主备切换后的专线访问

  • 红虚线:etcd 集群发生主备切换后的公网访问

etcd2etcd/zk2etcd 数据同步服务图如下所示:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第14张图片

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第15张图片

ZooKeeper 同步服务工程化实践

ZooKeeper 与 etcd 存储结构不一致,加大了同步的实现难度。ZooKeeper 存储是树状结构,而 etcd v3 是扁平结构。ZooKeeper 无法像 etcd 一样按照 prefix 来 list 所有 key;etcd 无法像 ZooKeeper 一样通过 list chilren 来查询某个目录下的子节点,也加大了实现同步的难度。

如何感知 ZooKeeper 中的数据变化?ZooKeeper 的 watch 不像 etcd 一样可以简单的感知到任意 key 的新增,需要递归的 watch 所有的节点,收到 ChildrenChanged 事件后拿到该事件对应节点下的所有子节点,再与 etcd 中的数据进行比对,就可以得到新增的数据,并将其同步 put 到 etcd 中。类似的,可以用递归的方法 watch 所有节点的删除事件,并同步删除 etcd 中的数据。

另外 ZooKeeper 的 watch 有着先天性的缺陷,watch 是一次性的,所以每次收到事件后又必须重新 watch,两次 watch 之间理论上是可能丢事件的,主要是在同一个 key 连续多次变更的时候可能会发生。如果丢事件发生就会破坏了数据一致性,我们引入了自动 diff 和订正的能力,即计算 ZooKeeper 和 etcd 中数据存在的差异,每次都会经过两轮 diff 计算,因为在频繁变更数据的情况下,一轮 diff 计算往往存在一些因不是强一致性同步导致的"伪差异",当 diff 计算出了结果就会自动 fix 掉这些差异。

如何解决与 etcd2etcd 共存?当同一个路径下,即有 etcd2etcd 同步写入的数据,又有 zk2etcd 写入的数据,在 zk2etcd 的自动订正逻辑里面,会计算出差异并订正差异,但我们不希望因此而误删 etcd2etcd 写入的数据。我们通过为 zk2etcd 引入了 Redis 来存储状态解决了这个问题,在 zk2etcd 往 etcd 中同步写入或删除数据时,也同步在 Redis 中记录和删除:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第16张图片

然后 zk2etcd 在自动订正计算差异的时候,只考虑本工具写入过的数据,避免误删其它同步工具写入的数据。

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第17张图片

etcd2etcd 工程化实践

为了解决 etcd 同步难题,我们调研了如下两种方案,接下来我们就详细介绍下它的原理:

etcd-syncer 之 mirror-plus 版

首先我们介绍下 etcd-syncer 的 mirror-plus 方案,顾名思义,它是 etcd 社区 make-mirror 的加强版。为了解决 make-mirror 的各种缺陷,它实现了以下特性、优点:

  • 支持多种同步模式,全量同步、断点续传,不再担忧专线、公网网络质量抖动

  • 高可用,负责同一数据路径复制的实例支持多副本部署, 一副本故障后,其他副本将在 5 秒后获得锁,在之前实例同步的进度基础上,进行快速恢复

  • 支持一致性检查(全量数据检查、快照检查)

  • 支持多实例并发复制提升性能(不同实例负责不同的路径),建议生产环境配置多实例,每个实例负责不同路径

  • 良好的运维能力,基于 Kubernetes Deployment 一键部署,丰富的 Metrics、日志,完备的 e2e 测试用例覆盖核心场景(http/https 场景,服务异常中断、网络异常等)

那么它的缺点是什么呢?因为它核心原理依然是依赖 etcd 的 mvcc+watch 特性,因此数据无法保证强一致性和只同步 key-value 数据。

  • 断点续传依赖 mvcc 历史版本保留时间,最好业务能保存至少 1 个小时的历史数据。

  • 当写请求较大的时候,备集群可能存在一定的数据落后,可能读到脏数据。

  • 不支持同步非 key-value 数据,如 auth 鉴权相关数据、lease 数据等。

etcd-syncer 之 Raft 版

为了解决所有类型的数据同步问题以及消除对 etcd mvcc 历史数据的依赖,腾讯云还可提供基于 Raft 日志的同步方案 etcd-syncer 之 Raft 版本。

它的部署图如下所示,etcd-syncer 同步服务作为一个类似 Learner 节点的身份,加入主 etcd 集群。

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第18张图片

主 etcd 集群 Leader 将 Raft 日志数据通过 MsgApp/Snapshot 等消息同步给 etcd-syncer,etcd-syncer 解析 Raft 日志,将 Raft 日志条目对应的 Txn/Delete/Auth 等请求应用到目的 etcd 集群。

它具备如下优点:

  • 具备 etcd-syncer 之 mirror-plus 版本的所有特性和优点,同时不依赖 etcd mvcc 历史数据。

  • 基于 etcd 底层的 Raft 日志同步数据,可以同步 key-value、auth、lease 等各种类型的数据。

  • 不依赖高版本的 etcd。

完备的容灾测试

grpc-proxy

此方案引入了 grpc-proxy 代理服务,也是头一次使用。为了了解此代理服务的性能情况,我们使用 etcd 自带的 benchmark 进行了读和写的测试,另外手写了一个小工具做了一下 watch 测试。以下为部分测试内容。

写入测试:

直接访问 etcd 服务的负载均衡入口:

9d5f12072ad9ab09a712fc1bf2c2462e.png

走 grpc-proxy 代理访问 etcd 服务的情况:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第19张图片

  • grpc-proxy 代理在 endpoints 配置走专线或公网情况下,都能正常写入

  • 写入 key 总数一定的情况下,连接数和客户端数越大,总耗时越低

  • 写入 key 总数越大,单次写入的平均耗时(Average)会有所增加,但仍为毫秒级

  • 当一次写入 key 总数为 10 万时,直连 etcdserver 会出现 too many requests 的报错,但 grpc-proxy 没有

  • 公网情况比专线性能有所下降

  • 走 grpc-proxy 代理的平均耗时相比直连有所增加,但满足需求

读取测试:

直接访问 etcd 服务的负载均衡入口:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第20张图片

走 grpc-proxy 代理访问 etcd 服务的情况:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第21张图片

  • grpc-proxy 代理在 endpoints 配置走专线或公网情况下,都能正常读取

  • 走 grpc-proxy 代理的平均耗时相比直连有所增加,但在可接受范围

watch 测试:

根据我们自己写的一个 etcdwatcher 服务对 grpc-proxy 进行 watch 测试:可以设置总 watcher 数量,更新频率,以及测试时间,结束时打印出简报报:

./etcdwatch -num=100 -span=500 -duration=10 -endpoint=http://grpc-proxy-addr:23791
test done
total 100 task
0 task failed
current revision is 631490
least revision is 631490
0 task is not synced

参数说明:

  • num 任务数量

  • span 更新间隔,单位毫秒

  • duration 总测试时间,单位秒

  • current revision:代表写入的 revision

  • least revision:表示 num 个任务中同步最慢的 revision

  • failed 为 0 说明正常;如果过出现 task not sync 说明 watch 和 put 不同步

以上测试结果来看:failed 数为 0,watch 测试正常。

zk2etcd

我们使用的是 1.2.5 版本,通过 Kubernetes 的 Deployment 方式部署。

1、模拟 zk server 失联

场景:

  • 通过将 hosts 中注入错误解析地址

现象:

  • 期间没有发现 zk 失联的报错日志

  • 监控指标没有发现异常

  • 此后执行重启,fixed 操作数没有出现凸增情况(在 1.2.4 版本中,存在 full sync 虽然在定时执行,但是并没有感知到需要 fix 的 key 的 bug。导致重启 zk2etcd 服务实例后,可能观察到 fixed 操作凸增的现象)

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第22张图片

2、模拟 Redis 失联

模拟操作:

  • 09:56:49 将 hosts 中注入 Redis 错误解析地址

  • 10:07:34 恢复 Redis

  • 10:16:00 重启同步服务 Pod(操作重启是为了观察 full sync 是否正常)

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第23张图片

现象:

  • 期间 fixed operation 数量没有增长,其他监控指标未发现明显异常

  • 实例重启后没有出现 fixed 数凸增的情况

3、模拟 etcd 失联

模拟操作:

  • 16:15:10 etcd server 失联

  • 16:30 恢复

  • 16:45 重启 Pod

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第24张图片

现象:

  • 期间 fixed operation 数量没有增长,其他监控指标未发现明显异常

  • 此后重启,fixed operation 数量有所增涨(不能确定是 full sync 未生效,还是重启后刚好有更新修复导致)

总结:

  • 只要 full sync 机制工作正常,各异常场景发生后,都能在下一个 full sync 触发后被恢复

  • 恢复的最小时间间隔取决于设置的 full sync 定时执行间隔时间(默认为 5m),业务对此间隔时间容忍情况自行调整参数

  • 此外,为了避免异常发生后,full sync 机制定时运行但也没能感知到情况发生,保险起见事后可以第一时间重启一下 zk2etcd 服务

  • 对于追加的 etcd 公网测试,full sync completed 和 zk、etcd 操作耗时,相比内网情况有一定(秒级)增长

etcd2etcd

etcd2etcd 的同步服务,我采用 Deployment 双副本部署。

1、多副本 backup 能力

期望:

  • ⼯作节点故障后备⽤节点会在 5s 后接管同步任务

测试方案:

  • etcd syncer 双实例部署

  • 杀掉正在运行的工作节点进行观察

结论:

不论是增量同步还是全量同步过程中,主备切换都能正常工作(需要注意的是,当全量同步中发生主备切换后会变为增量同步,从而可能导致比对较慢)

2、断点续传能力

期望:

  • 故障恢复后能从断点继续开始同步

其实在第 1 部分,备节点切换为主后接管同步工作,fast_path 变为 1 也证明了断点续传能力,我们还额外补充几个验证场景:

(a) 短时间故障

故障场景:中心 etcd 集群到热备集群的同步过程中,因作为源的中心 etcd 集群中也存在 -etcd-syncer-meta- 的 key,触发了同步服务报错(同 txn 中不能包含相同的 key),出现了数据差异

现象:将同步服务运行参数添加对 -etcd-syncer-meta- 的过滤,然后观察进过一段时间追赶数据后,最终 miss 数降去达到一致

(b) 长时间故障

故障场景:

  • 停止同步服务的部署 deployment

  • 等待两边 etcd 集群产生数据差异,并发生一次 compact 后再启动同步服务

现象:

  • 等产生数据差异,并发生 compact 后,重新启动同步服务,其日志如下:因 compacted 发生,触发全量同步

  • 同步服务监控指标:(a) dst miss key 很快降下去;(b) src miss key 有所增加,并持续不降

分析:

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第25张图片

  • 同步服务停止以后,源 etcd 的 key 数量发生不少变化,监控图看出期间有下降,说明发生过 key 的删除

  • 这里也暴露出一个小问题,当出现 src miss key 的时候,目前不能自动修复,需要人工接入清理多余的 key

3、reset 触发全量同步

当同步发生重大差异(如,发生 dst miss)进行紧急修复的时候,通过配置 --reset-last-synced-rev 参数删除断点续传信息,来触发全量同步修复差异。

现象:因某种异常,同步出现 dst miss(图中黄线实例)的情况。为了进行修复,新实例添加 --reset-last-synced-rev 参数后运行。

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第26张图片

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第27张图片

分析:

  • slow_path 为 1,说明触发全量同步(图中绿线实例)

  • 绿线实例的 dst miss 值没有增长起来,说明已经达到一致

4、网络故障

两 etcd 集群之间专线中断:

  • 增量同步中

  • 全量同步中

测试方案:当专线中断切换公网时,需要修改运行参数中的 etcd 集群访问地址,即:必会发生重启(重启场景测试前面已经涵盖,这里不再重复)。

总结:

  • etcd-syncer 同步服务有较好的主备机制,能够及时有效的进行切换

  • 短时间故障后的断点续传表现符合预期;对于长时间故障,同时发生 compact 的复杂情况时,恢复同步后出现 src miss 的情况,可能需要人工接入

  • 通过配置 --reset-last-synced-rev 参数对 src miss 的异常修复有较好的效果

作者介绍:

  • 孔令圳,斗鱼首席架构师,全面负责斗鱼全站技术架构体系规划和建设,10 余年中大型互联网产品架构经验,擅长高并发、高可用场景下的架构与方案设计。

  • 于竞,斗鱼技术保障运维专家,负责斗鱼高可用基础架构建设,擅长注册中心、监控体系等技术领域,同时也是斗鱼多活基础保障负责人。

  • 唐聪,腾讯云资深工程师,极客时间专栏《etcd 实战课》作者,etcd 活跃贡献者,主要负责腾讯云大规模 k8s/etcd 平台、有状态服务容器化、在离线混部等产品研发设计工作。

  • 陈鹏,腾讯云容器服务产品架构师,多年专注云原生领域,帮助了大量用户云原生容器化改造和生产落地,拥有丰富的一线实践经验,也发表了海量的云原生技术文章。

K8s线下实战与CKA培训

36a817f54ce4ff199a6b3c002d16360a.png

本次培训在北京开班,基于最新考纲,通过线下授课、考题解读、模拟演练等方式,帮助学员快速掌握Kubernetes的理论知识和专业技能,并针对考试做特别强化训练,让学员能从容面对CKA认证考试,使学员既能掌握Kubernetes相关知识,又能通过CKA认证考试,学员可多次参加培训,直到通过认证。点击下方图片或者阅读原文链接查看详情。

斗鱼基于etcd和ZooKeeper的注册中心实践案例_第28张图片

你可能感兴趣的:(运维,分布式,数据库,redis,java)