Honeycomb使用Apache Kafka为数据摄取提供高可用性缓冲管道


当您将遥测数据发送到 Honeycomb 时,Honeycomb 的基础架构需要先缓冲您的数据,然后再在我们的“检索器”列式存储数据库中进行处理。在 Honeycomb 的整个存在过程中,我们一直使用 Apache Kafka在我们的可观察性管道中执行此缓冲功能。
在这篇博文中,我们将回顾我们如何到达今天状态的历史,为什么我们对 Kafka 软件和硬件如此挑剔,以及我们如何认证和采用新的基于AWS Graviton2 的存储实例。最后,在本文的最后,我们将讨论在过去两年中进行累积优化后每兆字节吞吐量的价格下降。
 
Honeycomb 中 Kafka 的简要概述
使用 Apache Kafka 在摄取和存储之间缓冲数据,通过持久性/可靠性和我们的工程团队在可运维性方面使我们的客户受益。从而满足了每天向每项服务(甚至是有状态的服务)发送十几次来更快地进行创新。
Kafka 是如何帮助我们实现这些结果的?
首先,Kafka 拥有经过充分审核、久经考验的机制,用于保证单个消息的排序和持久性,使我们无需花费创新成本来编写我们自己的 Paxos/Raft 实现,也无需担心我们摄取工作者中的低级文件系统刷新。
其次,Kafka 确保多个读取器,例如负责给定分区的冗余检索器节点或计算服务级别目标 (SLO) 的Beagle 节点,可以就他们接收的数据达成一致。
第三,也是最后一点,使用 Kafka 使我们能够将无状态的“牧羊人”摄取工作者与有状态的“检索器”存储引擎分离,使我们能够执行滚动重启和更新,而不会导致客户停机。
AWS最近宣布,由 AWS Graviton2 处理器提供支持的 Amazon EC2 Im4gn 实例系列现已全面上市,我们很高兴采用它作为下一代,在未来几年为我们的 Kafka 集群提供支持。它还代表了我们必须使架构不可知的最后一个工作负载——Honeycomb 的每个服务现在都能够在 amd64 和 arm64 平台上以生产规模运行。
。。。。。
用我们的平台工程经理 Ben Hartshorne 的话来说,Kafka 是 Honeycomb 的“跳动的心脏”,为我们 99.99% 的摄取可用性 SLO 提供动力。
在供应商响应支持请求或将我们的 Kafka 主题永远锁定到供应商的托管代理之前,让我们的客户处于降级状态对我们来说是不可接受的。然而,这并不一定意味着我们自己完成所有的打包工作,因此在 2019 年 7 月我们进行了滚动重启,将自打包的 Kafka 0.10.0 转换为 Confluent Community 5.3(Kafka 2.3),使我们未来的验证和升级路径更容易.
适当调整 Kafka 的大小对我们来说是一个具有挑战性但很重要的问题,因为它代表了重大的基础设施支出和销售成本 (COGS) 的驱动因素。Kafka 需要调整以存储正确的数据量,并需要提供适当的网络、内存和计算。从历史上看,我们的业务需求意味着保留 24 到 48 小时的数据缓冲区,以防止检索器中的错误破坏客户数据的风险。如果我们在发布后的几天内发现错误,我们可以重放和重建数据以保持数据完整性。除了长期数据完整性用例,我们还在 Kafka 缓冲的数据窗口内使用短期召回作为普通操作的一部分。
当我们重新启动一个检索进程来部署一个新的构建时,我们会保留它在磁盘上的数据,但它需要重放在它关闭的几分钟内写入的数据。每当 AWS 淘汰托管检索器的实例时,我们都需要让该节点从头开始跟上速度。一个新的检索器节点只需要获取其前任的最新每小时完整文件系统快照,以及获取快照的 Kafka 偏移量。然后,它连接到 Kafka 并重播最多两个小时,从偏移量开始到现在。由于实例故障很少见,我们还特意使用此缓冲区并通过每周终止和更换一个检索器节点来验证我们的灾难恢复计划。
但是需要重播数天数据的情况很少发生,而如果我们试图让新的检索器节点赶上,我们需要非常快地返回过去一小时的数据。但也许有比每年在存储和 CPU 上花费数十万美元更好的解决方案,除非紧急情况,否则我们不会使用它。因此,在我在 Honeycomb 工作的近三年时间里,我们对支持 Kafka 集群的实例配置进行了三次改进,每次都针对当时最好的可用硬件来平衡性能、成本和利用率。
。。。。
 
混沌工程
混沌工程利用了我们在小学学到的科学方法:

  1. 观察:这正在发生。
  2. 作为一个问题:如果发生这种情况会怎样?
  3. 创建一个假设:如果发生这种情况,那么这将会发生。
  4. 进行实验。
  5. 多观察一些。
  6. 做决定。
  7. 再试一次,直到想要的结果。

我们设计了实验来证明风险,以验证我们的假设并验证我们使用的弹性技术将在生产中保持不变。
对于数据,Honeycomb 混合使用KafkaZookeeper和 Retriever(这是它自己开发的存储引擎来持久化数据)。该公司对其其余系统进行定期更改,但他们对其数据堆栈的更改仅少于每月一次。
大约一年前,他们开始询问有关这些长期运行的流程的问题,例如:
  • 如果其中一个意外重启会发生什么?
  • 即使它确实正确重启,你如何验证数据的完整性和一致性?
  • 如果一台机器重新启动会发生什么?
  • 他们的单点故障在哪里?

该团队通过在一个环境中一次仅重启一个 Zookeeper 来开始一项实验。然后他们观察变化。发生了什么?与稳态相比有任何变化吗?
他们意识到,当他们重新启动 Zookeeper 时,它停止向任何内部客户发送警报五到十分钟。他们观察到,他们的流程依赖于领导选举来运行这些 Honeycomb 警报的一份副本。
Honeycomb 团队随后进行了另一项实验,以确保他们正在测量的一切——他们的遥测——运行正常。如果某件事失败了,那么遥测应该同意它失败了。
Honeycomb 工程师确保解决他们的节点只与第一个 Zookeeper 实例对话的问题。但是当他们重新运行实验时,他们发现了另一个问题,该问题也导致 Zookeeper 无法正常重启。
重复实验使团队更上一层楼,以便在断电中幸存下来。
一旦您运行了几次实验,您就可以使用诸如 Gremlin 之类的混沌即服务工具集自动运行该实验。或者您可以手动继续。
通过 Gremlin,Honeycomb 现在每周至少自动重启一个节点,以验证 Kafka 复制是否正常工作,以及他们的系统是否可以从单个 Kafka 节点故障中恢复。
另外,Honeycomb 团队通过混沌工程发现了系统灵活性与节省的资金之间的直接关联。既然他们知道他们的节点可以按需重新启动,他们可以采用抢占式实例,这可以节省一半的成本。此外,他们不需要对这些实例性能执行主动混沌工程,因为他们现在知道他们将如何执行。
 
更多点击标题见原文