仪表板

如何零宕机将本地Kafka集群迁移上

发布时间:2022/7/2 16:32:02   
北京治疗白癜风哪家医院便宜 http://m.39.net/disease/yldt/bjzkbdfyy/
作者

NatanSilnitsky译者

Sambodhi策划

钰莹

本文最初发表于Medium博客,经原作者NatanSilnitsky授权,InfoQ中文站翻译并分享。

年,我们的团队致力于将Wix(国外比较火的一款建站平台)的个微服务从自托管的Kafka集群迁移到多集群的ConfluentCloud平台(ConfluentEnterprise的云端托管服务),整个过程是无缝的方式,无需服务所有者参与,且迁移是在正常通信中进行,没有任何停机。

这是我所领导过的最有挑战的项目,本文,我将与你分享我们作出的关键设计决策,并提供这种迁移的最佳实践和技巧。

    1分割过载集群

最近几年,由于事件驱动架构中的服务数量不断增多,Wix业务中大量的OLTP服务对Kafka的运转造成了负担。

我们的自托管集群规模从年的5KTopics,大于45K分区增加到年的20KTopics,大于K分区。

流量也从每天约4.5亿条记录增长到每个集群每天产生25亿多条记录。

迁移前Wix的Kafka使用情况

由于需要将所有元数据都加载到分区中,从而给集群控制器的启动时间带来了很大压力,这使得leader的选举时间大大增加。如果单个broker发生故障,也会极大影响其启动时间,从而造成更多的分区复制不足事件。

为防止Kafka集群在生产中出现不稳定的情况,我们决定将自托管的Kafka集群迁移到ConfluentCloud,并将每个数据中心的单集群分割成多个集群。

    2为什么要云托管Kafka集群?

自管理一个Kafka集群并非易事,尤其是在执行一些任务时,例如重新平衡brokers之间的分区,或者升级brokers版本等,这些必须认真规划和实施。特别是集群中过载了元数据时,这一点尤为明显,正如我们的情况一样。

以下是使用Kafka云平台,特别是ConfluentCloud的4个好处:

    更好的集群性能和灵活性

其中的brokers分区的重新平衡让其不会成为性能瓶颈,可以轻松扩大或缩小集群容量,以实现成本效益。

    透明的版本升级

Kafka的代码库不断得到改进,尤其是专注于KIP-:元数据将存储在Kafka内的分区中,而不是存储在ZooKeeper,控制器将成为该分区的leader。除了Kafka本身,不需要配置和管理外部元数据系统。这个项目一旦完成,将会极大地提高每个集群和brokers所能容纳的元数据量。通过管理,你可以实现对版本的自动更新,这样就可以改进性能并修正Bug。

    轻松添加新集群

如果你需要一个新的集群。设置它是非常简单的。

    分层存储

Confluent平台提供了分层存储,使得Kafka的记录保留期大大延长,而且不需要支付高昂的磁盘空间费用,通过将旧的记录转移到更便宜的S3存储,而不增加新的费用。

    3将个微服务切换到多集群Kafka架构

在Wix,我们拥有一个标准的JVM库和代理服务,用于与Kafka进行交互,称为Greyhound。这是一个开源的先进SDK,可以为ApacheKafka提供诸如并发消息处理、批量处理、重试等其他特性。

Greyhound是Wix约2个微服务的事件驱动主干,因此,引入多集群的概念仅需在一些地方(包括库和代理服务)就可以进行。由于旧的集群会自动映射,所以新主题的生产者(producer)和消费者(consumer)必须清楚地指明集群。当构建Greyhound消费者或生产者时,开发人员只要定义集群的逻辑名称即可,如下图所示:

    4如何分割

我们决定根据不同的服务级别协议(Service-levelagreement,SLA)对Kafka集群进行分割。例如,在CI/CD管道和数据迁移案例中,服务级别协议是有别于生产服务的。请注意,由于每个数据中心的作用不同,并非所有数据中心都拥有同样数目的Kafka集群。

Greyhound(Wix自己的KafkaSDK)懂得当服务实例在目前运行的数据中心集群不可用时,该如何处理这个问题并防止发生故障。

    5流量耗尽的数据中心?

为了使个微服务的生产者和消费者更容易迁移到多个管理式Kafka集群,最初的设计依赖于首先将每个数据中心(datacenter,DC)的流量全部耗尽。

这样的设计意味着只需要将生产者和消费者的连接细节切换到新的Kafka集群。因为Wix微服务通过Greyhound层与Kafka集群相连,所以只要在Greyhound的生产配置就可以更改连接(同时保证仅有一个数据中心受到影响)。

虽然这种设计非常简单,但是很遗憾,它不可能实现和执行。

有以下理由:

有些服务只部署在其中一个数据中心,并且难以进行迁移。这种设计意味着,(只可能出现两种极端局面)要么全有要么全无,并且当流量返回时,就会面临巨大的风险。未被切换的边缘案例可能会遭受数据丢失。数据中心的流量不能在很长一段时间内完全耗尽,因为这将极大提高一些服务的停机风险。

取而代之的是,计划了一种新的设计,包括在实时流量期间进行迁移。

    6零宕机迁移

在实时流量中执行迁移,就意味着必须进行细致的规划和实施。

这个过程需要逐步进行(一次只能对少量微服务产生影响,从而降低发生故障时的“爆炸半径”),并且可以实现完全的自动化,从而降低人为失误,其中包括自动化的回滚过程。

首先迁移生产者(在消费者之前)并非一种选项,这就意味着要花大量的时间来保证所有的消费者都已处理好了自托管集群中找到的所有记录,并能够安全地切换到新的集群主题。这会在处理过程中导致相当大的延迟,并且可能会损害某些OTLP业务流和用户。此外,如果没有数据丢失,由于一些意想不到的问题而回滚消费者是不可能的。

活跃的Kafka消费者在保证没有消息丢失和最小程度的重新处理记录的情况下,必须首先进行切换。唯一的方法是将所有消耗的主题记录从自己的主机集群复制到目标管理式集群。

  复制

为了保证在迁移过程中不会出现消息处理的丢失,我们创建了一个专门的复制服务。一旦所有的消费者主题被确定,复制器(replicator)服务就会被要求在适当的云集群中创建主题,并开始消费来自自托管集群的记录,并将它们生成到目标集群中。

  消费者迁移

为了促进消费者迁移,复制器还坚持为每个分区提供偏移量映射,这样Greyhound消费者就可以从正确的偏移量开始处理云集群中的记录——该偏移量是从自托管集群中第一个未提交的偏移量映射而来的。

除了复制器外,还有一个迁移编排器(MigrationOrchestrator),它可以确保一个主题被复制,所有的偏移量被映射,并继续请求Greyhound消费者从自托管集群中取消订阅。在验证成功后,编排器就会要求消费者在寻求正确的映射偏移时订阅云集群。

如果出现失败的情况,编排器能够要求消费者恢复到自托管集群。

所有这些编排器与消费者之间的通信都是通过专门的Kafka迁移主题实现的。Greyhound消费者在启动时就开始监听它们。

  生产者迁移

一旦某个主题的所有消费者都迁移了,就可以迁移其生产者。

最初的迁移设计需要请求生产者切换集群连接,同时仍然接受传入的生产请求。这就意味着将这些请求缓存到内存中,而且被人们认为相当危险。

之后,我们提出了一种更加简便的设计方案,它依赖于Wix的渐进式Kubernetes部署过程。每个新的pod只会在它的全部健康测试正常时,才会开始接受传入的请求,包括与Kafka的连接。因为这个过程都是逐步进行的,所以总会有“老”的pod在运行,所以服务作为一个整体,总是能接受到传入的请求。

在pod启动时,Greyhound生产者会简单地查看数据库来确定他们要连接的集群。这要比动态的集群切换和记录缓存更加简单。这就意味着可以安全地进行迁移,不会出现请求丢失,并且服务可以维持高可用性。

  复制的瓶颈

只有在迁移了生产者之后,才能终止对主题的复制。但是要想迁移生产者,就得把其所有的主题消费者都迁移出去。

事实证明,许多主题有来自不同服务的多个消费者,这就意味着,复制器消费者需要处理和复制的流量越来越多。

这就产生了一个问题,由于我们相对较老的自托管Kafkabrokers版本的技术局限性,使得消费者能够处理的主题数量有限。在几次尝试增加message.max.bytes的结果都适得其反(参阅KAFKA-bug),并造成了严重的问题后,我们决定简单地增加复制器消费者,并在它们之间分片处理要复制的主题。

  迁移之外——外部消费者控制

这种“有流量”的迁移设计为动态改变Greyhound消费者的配置或状态,提供了很多新的可能性,而无需在生产中采用新的版本。

现在,我们已经有了基础设施,使Greyhound消费者能够监听传入的命令来改变状态或配置。这样的命令可以包括:

切换集群:取消订阅当前集群并订阅另一个集群。跳过记录:跳过不能处理的记录。改变处理率:动态地增加或减少并行处理量,或为节流和背压添加延迟。重新分配记录:如果一个分区的延迟越来越大,则能够在所有分区之间重新分配记录(并跳过旧的记录)。

目前,这些都是理论上的,但利用已经存在的迁移基础设施就可以更容易地实现。

    7最佳实践和提示

以下是成功进行Kafka集群迁移的最佳实践和技巧清单:

    创建一个脚本,自行检查状态,如果没有达到预期状态就停止

让迁移过程尽可能地自动化是关键,所以让脚本能够自行检查是否能够进入下一阶段,这会极大地加速迁移过程。而另一方面,自动回滚和自我修复是很难做到的,因此,还是要交给人工干预。

    准备好随时可以使用回滚

无论你的迁移代码测试得有多好,生产环境都是不确定的。为每个阶段准备一个现成的回滚选项是非常重要的。一定要提前准备好,并在开始运行迁移之前进行尽可能多的测试。

    先从测试/中继主题和无影响主题入手

由于记录有可能丢失,或者恢复过程可能会很痛苦,因此迁移过程会非常危险。请确保用测试主题开始测试你的迁移代码。这样才能得到真正的检验。利用测试主题,通过将真实的生产记录复制到特定的测试应用中,实际模仿生产主题。这样,在消费者迁移时,万一发生失败,也不会影响到生产,但是会给你一个更加真实的生产模拟。

    创建自定义的指标仪表板,以显示当前和演变的状态

即便你创建了一个自动化的、完全无人值守的迁移过程,你也必须能够监控所发生的一切,并且当问题发生时,你拥有相关的工具可以进行调查。一定要事先准备好自定义的监控仪表板,以明确地显示你正在迁移的消费者和生产者的当前和历史状态。

在下图中,我们可以看出,生产者是如何成功地从自托管集群切换到管理式集群的(随着越来越多的Pod被重新启动并读取新的配置,因此吞吐量会降低)。

    确保自托管Kafka代理是最新的补丁版本

因为我们的自托管Kafkabrokers没有使用最新的补丁版本,所以在我们多次试图提高message.max.bytes的值时,我们最后还是发生了一个生产事故(详见本文的“复制的瓶颈”部分)。我的忠告是,先更新自托管集群Kafkabrokers版本。如果不是最新版本,那至少也要安装最新的补丁。

    8总结

我们利用Greyhound和专用编排服务和脚本,以便在实时流量期间以无缝方式实现自动、安全和逐步的迁移。

这可不是一件简单的事情。如果你可以充分利用数据中心完全耗尽流量的时间,或者可以承受得住处理的停机时间,那么我强烈建议将生产者和消费者切换到新集群,而不是首先复制数据。这样的设计更加容易,你也可以节省更多的时间。

否则,当你在流量下进行迁移时,你必须小心地按照执行的顺序(消费者在生产者之前/之后)进行迁移,并且要保证你明白这个决策的后果(回滚的能力,丢失数据的可能)。

下面你会看到一张流程图,使你容易理解各种选择。

作者介绍:

NatanSilnitsky,供职于Wix,后端基础设施开发者。

原文链接:



转载请注明:http://www.aideyishus.com/lkjg/848.html

------分隔线----------------------------

热点文章

  • 没有热点文章

推荐文章

  • 没有推荐文章