Agoda如何在Kafka上管理每天1.8万亿个事件

AgodaEngineering 2023-11-20 11:34:22
Agoda 是 Booking Holdings 集团(前身为 Priceline)的子公司,是一家提供在线酒店预订服务的专业网络旅游服务公司。其总部位于新加坡,在泰国曼谷开展业务。

 

本文介绍了kafka在Agoda中的应用。

 

图片

 

在 Agoda,我们每天通过 Apache Kafka 发送约 1.8 万亿个事件。我们于 2015 年首次开始使用 Kafka 来管理分析数据、将数据输入数据湖并实现近乎实时的监控和警报解决方案。

 

多年来,Kafka 在 Agoda 的使用量大幅增长(平均同比增长 2 倍),到 2023 年达到 1.8 万亿。现在,我们越来越多的工程团队在他们的应用程序中使用 Kafka。我们的 Kafka 用例已经扩大到不仅仅是作为分析数据管道。它现在充当异步 API,促进我们本地数据中心之间的数据复制,并在向机器学习管道提供数据和从机器学习管道提供数据方面发挥着至关重要的作用。

 

随着 Kafka 使用规模和快速增长,出现了必须解决的特殊挑战。在这篇博文中,我们将尝试概述我们多年来的旅程,并解释我们为不断发展的 Kafka 基础设施所采取的一些关键方法。

 

回归基础:简化开发人员向 Kafka 发送数据的方式

 

2015年,我们决定采用记录数据事件并单独将数据转发到Kafka的架构。这个想法很简单:客户端库(由开发团队使用)将事件写入磁盘,一个单独的守护进程(称为转发器)将读取磁盘上的事件并将其“转发”到 Kafka。

 

 
客户端库负责

 

  • 处理文件轮换

  • 管理写入文件位置

 

 
转发器负责

 

  • 读取文件并检索事件+元数据(例如 Kafka 主题、有效负载类型等)

  • 将事件发送到 Kafka

  • 跟踪发送内容的文件偏移量

  • 管理已完成文件的删除

 

图片

2-Step Logging Architecture

 

将日志记录到磁盘,然后转发到 Kafka(我们称之为两步日志记录架构)有几个好处,首先是将操作问题与开发团队分开。轻量级转发器将部署(作为守护进程服务)在我们基础设施中的每个节点上,并由 Kafka 团队直接管理。

 

 
Kafka 团队可以执行操作任务,例如

 

  • 远程动态配置转发器,将事件/主题路由到不同的 Kafka 集群或阻止它,而不会影响应用程序或需要开发团队进行更改。

  • 配置优化,例如 Kafka 批处理、压缩和延迟设置,无需开发团队的干预。

  • 独立于开发团队推出转发器升级。例如,我们可以推出 Kafka 客户端修复程序,而无需催促团队升级库依赖项。

  • 通过升级转发器来升级 Kafka,而无需追逐大量 Kafka 生产者(例如,如果 Kafka 客户端协议发生更改)。

 

图片

Separation of operational concerns

 

 
该架构的其他好处还包括

 

  • 为发送事件的生产者提供简化的 API,无需任何 Kafka 知识或依赖性(客户端库简化为简单的磁盘记录器)。

  • 通过将序列化逻辑嵌入到我们的客户端库中来强制执行序列化标准。例如,我们的客户端库可以通过与架构注册表协同工作来强制所有事件的 AVRO 序列化。

  • 写入磁盘增加了一层弹性,例如,在出现连接或 Kafka 问题时。

 

 
采取的权衡

 

通过我们的方法,客户端库严格依赖转发器进程来将数据发送到 Kafka。这意味着Kafka团队必须确保agoda中的每个节点都有一个健康运行的Forwarder进程,并且他们的任务是负责其部署、升级、监控和SLA。尽管这会导致架构更加复杂,但通过适当的监控和自动化工具可以轻松降低操作复杂性。

 

从本质上讲,主要的权衡是增加延迟以获得更好的弹性和灵活性;我们的两步日志记录架构仅用于发送分析数据。使用我们的方法,我们可以实现 10 秒的 99% 延迟,从应用程序客户端写入磁盘、转发器发送到 Kafka 到数据准备好使用的端到端测量。我们认为 10 秒的延迟对于大多数分析工作负载来说是可以接受的并且足够了。根据主题/集群用例,我们可以进一步调整转发器,以在 99% 时实现 1 秒的较低延迟(即,利用较小的批次,但总体吞吐量较低)。

 

 
如果我们需要低于 1 秒的延迟怎么办?

 

但是对于需要亚秒级延迟的关键和时间敏感的用例呢?此类应用程序仍将通过 Kafka 客户端库从其应用程序写入 Kafka,绕过两步日志架构。

 

我们相信这可以很好地平衡

 

  • 两步日志架构对于大多数(85%)只想将一些分析数据传递给 Kafka 并且没有亚秒级延迟要求(最多 10 秒的延迟是可以接受的)的 Agoda 开发人员来说非常简单。

  • 对于需要亚秒级延迟的特定但不太常见的用例,可以灵活地直接生成 Kafka。

 

考虑 Kafka 集群布局:每个数据中心使用多个较小的 Kafka 集群,而不是 1 个大型 Kafka 集群

 

在 Kafka 之旅的早期,我们还决定根据用例拆分 Kafka 集群,而不是每个数据中心使用单个 Kafka 集群。造成这种情况的主要原因有两个:

 

  • 隔离任何潜在问题及其对单个 Kafka 集群的影响;

  • 灵活地以不同方式设置和配置集群,例如,集群可以根据其用例具有不同的硬件规格和配置。

 

图片

Smaller Kafka Clusters based on use cases are easier to manage.

 

这种策略和两步日志架构(在上一节中解释)使我们能够透明地将 Kafka 事件路由到不同的 Kafka 集群,而无需通过转发器对生产者应用程序进行任何更改。尽管仍然需要对任何现有的消费者团队进行更改,但此类路由更改并不经常发生。此类路由配置的每个主题性质通常也意味着只有少数团队会受到此类更改的影响。

 

 
不要在Zookeeper上省成本

 

对于 Zookeeper,我们使用专用 SSD 磁盘分别配置专用物理节点(不与 Kafka 节点位于同一位置)用于 ZK 日志记录和快照数据目录。鉴于 Zookeeper 对于 Kafka 集群的健康运行至关重要,因此进行此设置是为了隔离 Kafka 和 Zookeeper 节点。我们希望先发制人地缓解 Kafka 和 Zookeeper 之间可能出现的任何潜在问题。到目前为止,这种设置效果很好;未来,计划迁移到较新的 Kafka 版本,完全删除 Zookeeper 作为依赖项。

 

建立信心:Kafka 监控和审计

 

“获得 Kafka Broker 统计数据还不够。我们需要开发人员和利益相关者相信他们生成/使用的数据是完整、可靠、准确和及时的。”

 

处理完 Kafka 布局和主要数据传输机制后,我们接下来要做的就是审计和监控 Kafka Pipeline。

 

为了进行监控,我们通过 JMXTrans 收集统计数据并将其传输到 Graphite 作为后端时间序列数据存储,并使用 Grafana 将指标可视化。然而,我们也明白仅仅获取 Kafka Broker 统计数据是不够的。我们需要开发人员和利益相关者相信他们生成/使用的数据是完整、可靠、准确和及时的。受到 KAFKA-260 的启发,我们开始将 Kafka 审计添加到我们的管道中。一个单独的线程将在我们的客户端库的后台运行(来自两步日志架构),跨时间段异步聚合消息计数以生成审核。

 

图片

Getting Audit Counts

 

图片Generating Audits throughout the Pipeline

 

然后,这些生成的审计通过管道传输到另一个 Kafka 集群,该集群仅用于在我们的许多 Kafka 集群中存储审计信息。我们重新使用了两步日志架构(在第一部分中解释)作为交付机制;通过为审计事件添加不同的 Kafka 端点。

 

审计信息最终到达 Whitefalcon(内部近实时分析平台)和 Hadoop,从而允许 Kafka 团队使用 Grafana 和 SuperSet 监控管道的运行状况并设置警报。Whitefalcon 中的数据还使 Kafka 团队在出现问题时更容易深入分析并查明问题。

 

图片Grafana Dashboards for High-Level Pipeline Monitoring based on Audits

 

 

图片SuperSet dashboard showing Kafka SLO based on Audits

 

在任何时间点,我们都可以确定有多少事件通过不同的管道阶段发送,从而使 Kafka 团队能够对 Kafka 管道的准确性和延迟有一个高级概述。与我们的 Kafka Broker Stats(graphite / grafana)一起,审计为我们提供了 Kafka Pipeline / Cluster 整体健康状况的全面视图。

 

跟上增长:了解何时扩展 Kafka 集群

 

我们的下一个挑战是弄清楚任何特定的 Kafka 集群何时需要扩展,即添加更多节点。天真地,我们一开始使用可用磁盘的百分比作为关键指标来确定集群是否需要扩展。我们很快发现这是一个坏主意,因为 Kafka 保留可以按主题动态配置,并且磁盘使用/容量指标不能准确反映 Kafka 集群容量。

 

由于许多因素都会影响 Kafka 集群的总体可用容量,例如 CPU、网络、磁盘和分区总数。在第二次迭代中,我们希望对集群容量进行更全面的衡量,并考虑多个资源指标。

 

我们想要测量的每个资源指标都将与上限进行比较,上限定义为我们可以放心让集群运行的最大限制。这将被记录为当前资源指标/上限并以百分比表示。然后,我们将所有百分比中的最大值作为集群的总体容量。这将容量简化为一个数字,它表明了当时可用容量的主要资源限制。

 

图片

Capacity is calculated based on the dominant cluster resource/limit at that time.

 

我们在 Kafka 集群中监控的关键容量指标(每个集群):

 

  • 使用的磁盘存储

  • 网络使用情况

  • CPU使用率

  • 每个集群的总分区数

  • 请求处理程序平均空闲百分比

 

通过根据每个集群得出的总体容量百分比设置警报阈值,团队可以研究容量限制并决定是否存在需要进一步调查的问题,或者是否需要物理扩展集群。随后,采用这种计算集群容量的方式后,我们发现容量数字在集群缩小时也很有用。

 

确保健康的数据增长:将成本归还给团队

 

随着这些年来数据持续增长,大约一年多前,我们开始问自己需要多少数据。人们开始认为数据平台(包括 Kafka Pipeline 和我们的数据湖)已经变成了垃圾场。发送/存储的大部分数据没有产生价值。

 

为了解决这种情况,我们借鉴了云提供商的做法:对使用情况进行货币价值并将其归因于用户。核心概念很简单:让开发团队对他们使用的内容(在我们的例子中是 Kafka)负责,并对所产生的成本负责。

 

对于 Kafka 来说,为团队的使用生成货币价值意味着选择一个合适的指标来衡量和分配成本。为了简单起见,我们最终选择了发送的字节。我们故意选择忽略消费者的使用,因为我们不想惩罚消费数据的团队,因为数据民主化的全部目的是允许人们使用数据。相反,我们认为联合国正在组建数据团队来证明发送/存储数据的合理性。

 

在 Agoda,每个 Kafka 主题都会分配一个所有者团队作为主题创建过程的一部分,从而使整个成本归因过程更容易实施。为了确定每字节的成本,我们将 Kafka 集群的总成本与派生的集群容量数字(来自上面的了解何时扩展 Kafka 集群部分)一起推断出估计的 100% 容量以及这将需要多少总容量每天字节。从那里,我们可以得出每字节的估计成本,用于我们的成本归因模型。

 

图片

Attributing Costs back to Teams based on a derived cost per byte.

 

推出后,我们发现将团队发送的数据赋予货币价值的能力对于激励团队评估他们需要/不需要什么非常强大。总体而言,它改变了团队对成本管理的思维方式,并鼓励他们积极主动地管理成本并成为公司资源的良好管理者。最终,这演变成了 agoda 范围内一项更重要的工作,将任何系统的成本归咎于任何开发团队,但这也许是另一个博客主题了。

 

通过仪式:身份验证和 ACL

 

生产中任何不断发展的 Kafka 集群有时都需要添加 Kafka 身份验证和 ACL(假设您开始时没有身份验证和 ACL)。

 

在 Agoda,当我们刚开始时,我们的集群最初仅用于应用程序遥测数据,当时不需要 Kafka 上的身份验证和 ACL。然而,随着我们的 Kafka 使用量随着时间的推移而激增,我们开始担心我们无法识别和处理滥用用户并对 Kafka 集群性能产生负面影响的情况。

 

澄清一下,我们的两步日志架构(参见上面的第一部分)为我们提供了一些保障措施,因为如果突然发生大量事件,我们可以阻止转发器。尽管如此,随着 Kafka 使用量的增长,团队需要直接连接到 Kafka(绕过转发器)的用例越来越多。此外,新的要求不断出现,我们需要限制用户对某些主题的访问。

 

幸运的是,在 Kafka 中实现身份验证和 ACL 已有详细记录。我们结合公司的具体要求收集了文件中的信息。我们于 2021 年完成并发布了 Kafka 身份验证和授权系统。另外一点是,我们添加了额外的组件来生成凭据并将其分配给该身份验证系统,并让团队通过自助服务请求 Kafka 凭据和 ACL。

 

图片Additional components for Authentication & Authorization

 

 

有了这个认证和授权系统,

 

  • Kafka 团队现在能够管理用户、设置凭证的过期时间、阻止和允许用户访问特定主题等。此外,它还可以让 Kafka 团队更轻松地通过 ACL 阻止人们访问受保护的主题,从而防止敏感数据泄露。

  • 用户可以确保他们的主题是安全的,并且只能由特定团队读取和写入。

 

接下来,我们正在 Kafka 中测试证书身份验证和通过 SSL 加密数据,以使我们的 Kafka 更加安全。这可能会降低 Kafka 的整体性能,但我们认为值得尝试。

 

不要忘记操作可扩展性:自动化工具

 

最后,我想简单谈谈自动化工具的主题。随着我们管理越来越多的 Kafka 集群,我们知道我们需要更好的工具来帮助我们并确保操作流程保持可扩展性。

 

目前,在 Agoda,我们混合使用开源 Kafka 工具,例如 Cruise Control、Kafka UI、一些用于二进制部署的内部构建工具、Broker 配置传播、Kafka Broker 滚动重启以及用于管理 ACL 的 UI,等等很少。我认为我们永远不会停止不断寻找新的、更好的工具来添加到我们的工具库中,以及它是大规模管理此类系统的重要组成部分。

 

结论:那么到底是怎么回事呢?

 

Apache Kafka 是一款高度可扩展、强大的软件,总体来说相对易于管理。我们发现大规模的主要挑战与 Kafka 软件本身关系不大,而更多地与其他方面有关,例如:

 

  • 将运营问题与开发团队分开。

  • 考虑您的 Kafka 集群布局(例如,集群如何隔离以及数据如何发送)。

  • 知道何时扩大/缩小 Kafka 集群。

  • 添加监控和审计,并让开发团队了解其使用情况和成本。

  • 采取保障措施来快速识别和隔离管道中可能的不良行为者。

 

下一步是什么?改进转发器

 

对我们的两步日志架构的一个批评是在运行时,如果 Kafka 收到消息,客户端无法得到确认(因为客户端所做的只是写入磁盘)。截至撰写本文时,我们正在重新审视转发器架构,并计划合并一个端点,该端点将在 Kafka 确认消息后向客户端库提供响应。

 

总之,多年来我们在扩展 Kafka 集群方面学到了很多东西。随着我们支持 Agoda 不断增长的需求,我们的kafka之旅将不断发展。

 

免责声明:本博文中列出的方法是根据 Agoda 的具体要求量身定制的,我们绝对不是说您应该这样做;与大数据中的许多其他事物一样,不要盲目跟随。尝试并做对您的需求有意义的事情。

 

来源丨AgodaEngineering

编译丨公众号:大数据技术体系(ID:BigDataTechStack)

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn
最新评论
访客 2024年04月08日

如果字段的最大可能长度超过255字节,那么长度值可能…

访客 2024年03月04日

只能说作者太用心了,优秀

访客 2024年02月23日

感谢详解

访客 2024年02月20日

一般干个7-8年(即30岁左右),能做到年入40w-50w;有…

访客 2023年08月20日

230721

活动预告