Apache Kafka: 优化部署的10个最佳实践

时间:2022-01-20 05:16:30

原文作者:Ben Bromhead      译者:江玮

原文地址:https://www.infoq.com/articles/apache-kafka-best-practices-to-optimize-your-deployment

关键点

  • Kafka的低开销和易于水平伸缩的设计使得它能基于廉价硬件高效地运行。
  • 使用最好的磁盘为ZooKeeper提供强大的网络带宽,分别存储日志,隔离ZooKeeper进程,禁用交换以减少延迟。
  • 将Kafka的默认复制因子从2增加到3,这在大多数生产环境中都是合适的。
  • 更多的分区意味着更大的并行化和吞吐量,但分区也意味着更多的复制延迟、重新负载均衡和文件句柄资源。
  • 监视系统指标,如网络吞吐量、文件句柄、内存、负载、磁盘使用情况,以及JVM统计数据,如GC和堆使用情况。

Apacha Kafka以著名奥匈帝国小说家卡夫卡命名(注1),并且没有辜负这个名字。它对后端技术人员充满吸引力;产品具备深度和挑战性;当足够全面理解后,同样能带来的丰厚回报。遵循Kafka的一系列最佳实践,可以使这个强大的数据流平台的使用和管理变得非常容易且有效。

注1:弗兰兹·卡夫卡,生活于奥匈帝国的捷克德语小说家,本职为保险业职员。主要作品有小说《审判》、《城堡》、《变形记》等。深受尼采、柏格森哲学影响,作品大都用变形荒诞的形象和象征直觉手法,表现被充满敌意的社会环境所包围的孤立、绝望的个人。

以下是10个技巧可以优化Kafka部署并更使之容易管理:

  1. 设置日志配置参数确保日志可管理
  2. 了解Kafka的硬件需求
  3. 充分利用Apache ZooKeeper
  4. 正确设置复制和冗余策略
  5. 合理配置Topic
  6. 使用并行处理
  7. 在考虑安全性的情况下配置和隔离Kafka
  8. 通过提高Ulimit避免停机
  9. 保持较低的网络延迟
  10. 有效利用监控和警报

接下来让我们逐一详细看看这些最佳实践。

 

  1. 1.  设置日志配置参数确保日志可管理

Kafka为用户提供了大量的日志配置选项,虽然默认设置是合理的,但是更好的方式是根据实际的业务情况,自定义日志行为以匹配特定需求。包括设置日志保留策略、清理、压缩。

可以使用log.segment.bytes,log.segment.ms和log.cleanup.policy来控制日志行为。如果在业务中不需要保留大量历史日志,可以通过设置cleanup.policy来清理特定大小的日志文件,或者设定在某个时间点清理。此外还可以将其设置为“compact”,以便在需要时保留日志。日志文件清理会消耗CPU和RAM资源,清理、压缩的频率和性能需要小心权衡。

压缩是Kafka确保每个消息键至少保留最后一个已知值的过程(在单个Topic分区的数据日志中)。压缩操作会对Topic中每个键进行处理,只保留其最后一个值,并清除所有其他重复项。在删除时,键值会被设为“null”(它被称为“tombstone”,形象地表示删除)。

Apache Kafka: 优化部署的10个最佳实践

图1- Kafka日志压缩过程

Kafka日志相关参考文档:
Log
Compaction Basics

  1. 2.  了解Kafka的硬件需求

虽然许多不熟悉Kafka的团队会高估它的硬件需求,但实际上Kafka开销很低而且在设计上对水平扩展很友好。这使得使用廉价的硬件就可以高效地运行Kafka:

  • CPU:除非需要SSL和日志压缩,否则Kafka不需要强大的CPU。同时,使用的核越多,并行性越好。在大多数情况下,可以使用LZ4来提升性能。
  • RAM:在大多数情况下,Kafka可以使用6GB的RAM来优化堆空间。对于特别重的生产负载,使用32GB或更多。额外的RAM将用于支持OS页面缓存和提高客户机吞吐量。虽然Kafka可以用更少的RAM运行,但是当可用内存更少时,它处理负载的能力就会受到限制。
  • Disk:Kafak在RAID设置中使用多个驱动器时非常有用。RAID在底层实现了物理磁盘的负载均衡和冗余,虽然会牺牲一些磁盘空间和写入性能。在配置中使用多目录,每个目录挂在在不同的磁盘(或者RAID)上。由于Kafka的顺序磁盘I/O范式,SSD没有提供多少优势,此外不应该使用NAS(注2)。
  • Network & File:建议使用XFS(注3),如果环境允许,建议将集群部署在单个数据中心。与此同时传输的网络带宽应尽可能充足。

注2:NAS(Network Attached Storage:网络附属存储):连接在网络上具备资料存储功能的装置,也称为“网络存储器”。它是专用数据存储服务器,将存储设备与服务器彻底分离,集中管理数据。

注3:XFS是一个64位文件系统,最大支持 8exbibytes 减1字节的单个文件系统,实际部署时取决于宿主操作系统的最大块限制。对于一个32位Linux系统,文件和文件系统的大小会被限制在 16tebibytes。

Apache Kafka官网还包含专门的硬件和OS配置内容,其中提供了宝贵的建议。关于Kafka负载/性能测试的其他有用链接如下:

Benchmarking Apache Kafka: 2 Million
Writes Per Second (On Three Cheap Machines)

Load Testing Apache Kafka on AWS
Performance testing

  1. 3.  充分利用Apache ZooKeeper

运行的Apache ZooKeeper集群是运行Kafka的关键依赖项。但是当使用ZooKeeper和Kafka一起使用时,有一些重要的最佳实践需要注意。

ZooKeeper节点的数量一般最多5个。一个节点适合于开发环境,对于大多数生产环境三个节点的Kafka集群足够了。虽然大型Kafka部署可能需要5个ZooKeeper节点来减少延迟,但是必须考虑节点上的负载。如果7个或更多的节点同步和处理请求,整个系统的负载将变得非常大,性能可能会有明显的影响。(虽然最新版本的Kafka在Zookeeper上的负载要比以前版本低得多,以前的版本使用Zookeeper来存储消费偏移量。)

最后正如Kafka的硬件需求一样,为ZooKeeper提供尽可能充足的网络带宽。使用最好的磁盘、单独存储日志、隔离ZooKeeper进程和禁用交换也会减少延迟。下表突出显示了不同Kafka版本中依赖Zookeeper的一些控制台操作。早期版本0.8.0在控制台没有很多可用的功能。从0.10.0.0开始,我们可以看到一些主要的功能移出了Zookeeper,从而降低了Zookeeper的利用率。

Apache Kafka: 优化部署的10个最佳实践

适当的管理意味着Kafka部署的弹性,一个重要实践是将Kafka默认复制因子从2增加到3,这在大多数生产环境中都是合适的。这样做可以确保即使其中一个broker失效也不用担心,甚至损失两个broker也不会影响系统的可用性。另一个需要考虑的是数据中心机架区域。例如,如果使用AWS, Kafka服务器应该位于相同的区域,但同时也要考虑多个可用性区域来实现冗余和弹性。

  1. 4.  正确设置复制和冗余策略

机架部署需要考虑的Kafka配置参数为:

broker.rack=rack-id

正如Apache Kafka文档中所述:

When a topic is created, modified
or replicas are redistributed, the rack constraint will be honoured, ensuring
replicas span as many racks as they can (a partition will span min(#racks,
replication-factor) different racks).

一个例子:

考虑三个机架上分布的9个Kafka代理(B1-B9),如下图所示:

Apache Kafka: 优化部署的10个最佳实践

图2- Kafka集群具有机架感知

图中具有三个分区(P1、P2、P3)和复制因子为3 (R1、R2、R3)的单个Topic将为每个机架中的一个节点分配一个分区。这个场景提供了高可用性,每个分区都有两个副本,即使整个机架故障(如图上所示)。

  1. 5.  合理配置Topic

Topic配置对Kafka集群的性能有很大的影响。由于上生产之后再对复制因子或分区计数等设置的进行更改,有可能影响线上,因此尽可能在初始时就以正确的方式估算并设置好配置。如果需要更改或创建新Topic,确保在Stage环境中测试该新Topic。

把复制因子改为3时,在处理大型消息时要深思。如果可能的话,将大消息分成有序的多个片段,或者使用指向数据的指针(例如主键)。如果这些方式都无法采用,建议在生产端启用压缩。默认的日志段大小是1 GB,如果消息更大,必须仔细分析业务场景。分区(Partition)计数也是一个非常重要的设置,将在下一节详细讨论。

Topic配置有默认值,可以在创建时覆盖,也可以在稍后进行特定配置时覆盖。如上所述,最重要的配置之一是复制因子(replication factor)。以下示例演示了从控制台创建Topic,复制因子为3,以及使用其他“Topic级别”配置的3个分区:

bin/kafka-topics.sh
--zookeeper ip_addr_of_zookeeper:2181 --create --topic my-topic --partitions
3 --replication-factor 3
--config max.message.bytes=64000 --config
flush.messages=1

获取Topic级别配置的完整列表可以参考官方文档

  1. 6.  使用并行处理(Parallel Processing)

Kafka是为并行处理而设计的,就像并行化本身一样,充分发挥它需要掌握平衡的艺术。分区计数是一个Topic级设置,分区越多,并行化和吞吐量越大。然而分区还意味着更多的复制延迟、重新负载均衡和大量文件句柄。

找到最佳分区设置并不复杂,可以计算基于当前硬件期望达到的吞吐量,然后计算所需的分区数量。根据保守的估计,单个Topic上一个分区可以交付10MB /s,以此进行推断,可以获得所需的总吞吐量。另一种方法是为每个broker每个Topic使用一个分区,然后进行性能测试并检查结果,如果需要更大的吞吐量,则将分区加倍。

Overall, a useful rule here is to
aim to keep total partitions for a topic below 10, and to keep total partitions
for the cluster below 10,000. If you don’t, your monitoring must be highly
capable and ready to take on what can be very challenging rebalances and
outages!

The number of partitions is set
while creating a Kafka topic as shown below.

一般来说,Topic的总分区建议保持在10以下,并将集群的总分区保持在10,000以下。如果分区数远多于此,那么必须做好完善的监控并且服务中断做好预案。

以下是在创建Kafka主题时设置分区的数量:

bin/kafka-topics.sh
--zookeeper ip_addr_of_zookeeper:2181 --create --topic my-topic --partitions
3 --replication-factor 3
--config max.message.bytes=64000 --config flush.messages=1

此外,也可以在创建之后增加分区计数。但是它会影响消费端,因此建议在考虑清楚所有后果之后再执行此操作。

bin/kafka-topics.sh
--zookeeper zk_host:port/chroot --alter --topic topic_name --partitions
new_number_of_partitions

  1. 7.  在考虑安全性的情况下配置和隔离

Kafka安全部署主要两点:1) Kafka的内部配置,2) Kafka运行的基础设施。

Kafka .9版本包含了许多有价值的安全特性,例如Kafka/client和Kafka/ZooKeeper身份验证支持,以及TLS支持。虽然TLS会对吞吐量和性能带来成本,但它有效地地隔离和保护Kafka broker的流量。

隔离卡Kafka和ZK对安全至关重要。除了特殊情况,ZK不应该连接到公网,应该只和Kafka沟通(如有共用情况则另说)。防火墙和安全组应该隔离Kafka和ZooKeeper,将broker驻留在私有网络中并拒绝外部连接。中间件或负载平衡层应该将Kafka与公网客户端隔离。

Kafka的安全选项和协议如下

  • SSL/SASL:客户端到代理、内部代理、代理到工具的身份验证。
  • SSL:客户端到代理之间、代理之间以及工具到代理之间的数据加密
  • SASL类型:SASL/GSSAPI
    (Kerberos)、SASL/PLAIN、SASL/冲压- sha -512/冲压- sha -256、sasl_auth载体
  • Zookeeper安全性:客户端的身份验证(代理、工具、生产者、消费者),ACL授权。

使用SASL_SSL进行安全设置的示例配置:

#Broker configuration
listeners=SSL://host.name:port,SASL_SSL://host.name:port
advertised.listeners=SSL://host.name:port,SASL_SSL://host.name:port

security.protocol=SASL_SSL
security.inter.broker.protocol=SSL listener.security.protocol.map=INTERBROKER\:SSL,PUBLIC_CLIENT\:
SASL_PLAINTEXT,PRIVATE_CLIENT\:SASL_PLAINTEXT
ssl.keystore.location=/var/private/ssl/server.keystore.jks

ssl.keystore.password=test1234
ssl.key.password=test1234

ssl.truststore.location=/var/private/ssl/server.truststore.jks

ssl.truststore.password=test1234
sasl.mechanism.inter.broker.protocol=PLAIN sasl.enabled.mechanisms=PLAIN

#Client Configuration
(jaas file) sasl.mechanism=PLAIN

sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule
required \

username="[USER
NAME]" \

password="[USER
PASSWORD]";

  1. 8.  通过提高Ulimit避免停机

常见的问题场景:broker由于负载太高而下线,本质上是由于占用了大量文件句柄导致的错误。通过编辑/etc/sysctl.conf并将Ulimit配置为允许128,000个或更多的打开文件,可以避免这种错误。

增加CentOS的ulimit的一个例子:

1)创建新文件/etc/security/limits.d/nofile.conf

2)输入以下内容:

* soft nofile 128000

* hard nofile 128000

3)重启系统或服务。

4)通过以下命令进行验证。

*ulimit -a

*以外还有很多方法可以增加ulimit。可以针对实际的Linux发行版,使用任何合适的方法。

  1. 9.  保持较低的网络延迟

为了降低Kafka部署的延迟,确保broker在地理上位于离客户最近的区域,并确保在选择云服务商提供的实例时考虑网络性能。如果硬件、带宽等因素影响服务质量,可以考虑在基础设施及硬件上进行有价值的投资。

  1. 10.       有效利用监控和警报

在创建Kafka集群时,遵循上面的实践可以避免许多问题,但仍要保持警惕,在问题出现之前识别并正确处理。

监视系统指标(如网络吞吐量、打开的文件句柄、内存、负载、磁盘使用情况及其他因素),监视JVM统计数据(包括GC和堆使用情况)等都是必要的。仪表板和历史记录工具可以大大提高问题发现的时效。与此同时,可以通过Nagios或PagerDuty等系统配置延迟峰值或磁盘空间不足等预警,以便在问题如滚雪球一样越滚越大之前得到妥善解决。

通过Instaclustr控制台显示的Kafka监控图示例:

Apache Kafka: 优化部署的10个最佳实践

Apache Kafka: 优化部署的10个最佳实践

Apache Kafka: 优化部署的10个最佳实践

原文作者:Ben Bromhead 
译者:江玮

原文链接:https://www.infoq.com/articles/apache-kafka-best-practices-to-optimize-your-deployment

版权声明:本文版权归作者(译者)及公众号所有,欢迎转载,但未经作者(译者)同意必须保留此段声明,且在文章页面明显位置给出,本文链接如有问题,可留言咨询。