Apache Kafka性能测试(3):Broker调优结果
发布日期: 2018年11月1日
作者: 伊藤雅博,日立制作株式会社
首先
本帖介绍了我在2017年企业级开源会议上发表的“目标!成为Kafka大师 ~如何在Apache Kafka中发挥最佳性能~”演讲的验证调查内容(共8次)。本帖内容是基于2017年6月发布的Kafka 0.11.0的版本。
这一次是第六次,我们将介绍Broker的调优结果。在上一次的投稿中,我们优化了Producer-Broker之间的通信吞吐量。在进行了这一优化之后,这次我们将分别调优Broker的日志刷新性能和Broker之间的复制性能,以进一步优化吞吐量。
投稿一覧:
1. Apache Kafka的概述和架构
2. Apache Kafka的生产者/代理/消费者工作原理和配置列表
3. Apache Kafka的推荐配置和性能估算方法
4. Apache Kafka的性能验证(1):验证环境和参数调优内容
5. Apache Kafka的性能验证(2):生产者调优结果
6. [Apache Kafka的性能验证(3):代理调优结果(本投稿)
7. Apache Kafka的性能验证(4):生产者再调优和消费者调优结果
8. Apache Kafka的性能验证(5):整体系统延迟问题
调整经纪人日志刷新性能
首先,我们将优化包括Broker日志刷新在内的吞吐量。我们在下图中以红色表示了调整范围。
将 acks 修改为 1。
在第5次提交中,为排除Broker的日志刷新和复制的影响,我们进行了acks=0的调优。在本次验证中,为了验证包括Broker日志刷新在内的性能,我们将acks设置为1。下面是将acks从0更改为1时吞吐量的变化。
在本次验证中,我们使用复制因子=3进行测量,即将产生的数据在Broker之间复制两倍数量,以便更容易比较复制吞吐量和生产/消费吞吐量。因此,我们显示了一半的值。
当将acks更改为1时,生成的吞吐量略有下降,但仍然可以确认它保持接近于理论值1,170MB/s1的吞吐量。
日志刷新调度器间隔时间(log.flush.scheduler.interval.ms)的优化
下面展示了在调整Log Flush间隔(log.flush.scheduler.interval.ms)时的吞吐量变化。最左边的图表表示默认设置(Long型最大值),Kafka会依赖操作系统的后台刷新功能,而不进行显式的刷新操作。
即使更改了闪光间隔,Produce的吞吐量几乎没有变化。通过这个测量结果,确认了闪光间隔在默认设置下没有问题。
num.io.threads的调整
下面展示了调整了请求处理程序线程数(num.io.threads)的结果。
修改线程数后,生产吞吐量基本保持不变。通过此次测试,确认请求处理程序的线程数使用默认的8个是没有问题的。
日志闪存性能调优结果总结
我已将Broker的日志刷新性能调优结果总结如下。
在本次验证中,不需要对日志刷新性能进行调优。这是因为磁盘I/O性能的理论值高于网络I/O性能,并且磁盘I/O不成为瓶颈的原因。结果是,生产者的发送吞吐量在acks=1的情况下达到1,164 MB/s,依然接近理论值(1,170MB/s)的吞吐量。
对Broker之间的复制性能进行调优
下一步是优化包括Broker之间的复制在内的吞吐量。在这个验证过程中,我们将进行调优,以确保复制吞吐量的变化。最初,我们将使用acks=1进行调优。然后,在复制吞吐量改善到与生产吞吐量相匹配之后,我们将将acks设置为all,并进行测量。我们将在以下图表中用红色表示调优范围。
调整 replica.fetch.response.max.bytes 参数的值。
首先,我們將展示更改 Replica fetcher 在一次 Fetch 請求中獲取的最大大小(replica.fetch.response.max.bytes)的結果。我們將設置一個較大的值(100MB)給該參數,然後通過調整以分區為單位的最大獲取大小(replica.fetch.max.bytes)來調整獲取的大小。
通过这个更改,Replicate的吞吐量略微提高,从278 MB/s增加到287 MB/s。
调整 replica.fetch.max.bytes 的参数
以下是调整了Replica fetcher在单个Fetch请求中获取的Partition单位的最大大小(即replica.fetch.max.bytes)的结果。
通过将此参数从1MB增加到5MB,复制吞吐量从287MB/s提高到356MB/s。
调整 num.replica.fetchers 和 num.network.threads。
当增加复制抓取进程数(num.replica.fetchers)时,会增加与经纪人之间的连接数,从而给经纪人的套接字服务器带来负载。因此,我们同时调整了复制抓取进程数和套接字服务器的网络线程数(num.network.threads)。以下是通过此调整获得的复制吞吐量的变化情况。
通过调整 num.replica.fetchers ,我们可以显著增加性能,而 num.network.threads 的影响较小。随着 num.replica.fetchers 的增加,吞吐量会不断提高,但当 num.replica.fetchers 是3的倍数时,吞吐量有下降的趋势。稍后我们将解释原因。
经过测试,当将num.replica.fetchers从1增加到16时,Replicate吞吐量从356MB/s提升到784MB/s。下面展示了在num.network.threads=9条件下,Produce/Replicate/Consume的吞吐量变化。
随着num.replica.fetchers的增加,Produce吞吐量下降,而Replicate吞吐量上升。当num.replica.fetchers=16时,确认Replicate吞吐量(784MB/s)和Produce吞吐量(780MB/s)几乎达到平衡。
将 “acks” 更改为 “all”。
以下是将 acks 从 1 更改为 all 时的吞吐量。由于本次验证是在 min.insync.replicas=2 的条件下进行的,因此设置 acks=all 可以在确认数据已被复制到 Leader 副本和至少一个 Follower 副本后,开始向 Producer 返回响应。
尽管在acks = 1的时候,Produce和Replicate的吞吐量几乎是相等的,但是当设置acks = all时,吞吐量却显著下降。
复制性能的调优结果总结
我总结了经纪人之间复制性能调优的结果如下。
在本次验证中,通过将acks设置为1,我成功将复制吞吐量提升至784MB/s。然而,当将acks更改为all时,吞吐量大幅下降至405MB/s。
对于 Replica fetcher 的 Partition 分配的不均衡情况
在本次验证中,当 num.replica.fetchers 是3的倍数时,复制性能下降。这是由于对于 Replica fetcher 的 Partition 分配不均衡造成的。
例如,假设有3个Broker,分配了6个Partition(的Leader Replica)。在创建主题时,Partition 0的Leader Replica将被分配到任意一个Broker,而Partition 1及其后续的Partition将按照Broker ID的顺序分配(请参考AdminUtils.scala和PartitionStateMachine.scala)。例如,如果将Partition 0(的Leader Replica)分配给Broker1,则将形成以下对应关系。
如果每个 broker 都有三个 replica fetcher 线程,每个 replica fetcher 线程将负责哪个 partition?首先,replica fetcher 0 将被分配给某个 partition,然后 replica fetcher 1 开始依次按照 partition ID 进行循环分配(参考 AbstractFetcherManager.scala)。例如,如果 replica fetcher 0 被分配给 partition 1,那么将形成以下对应关系。
根据上述算法,如果Replica Fetcher数是Broker数的倍数,每个Replica Fetcher将被分配给同一个Broker的Partition。因此,每个Replica Fetcher只负责自己Broker的Partition,不再被使用(Replica Fetcher用于获取其他Broker上的Partition数据)。这将导致复制性能下降。
另外,如果有多个主题,副本提取器的分配将会分散,从而减轻这种不均衡。
最后
这次我们介绍了经纪人的调整结果,但是当将acks设置为all时,吞吐量显著下降。这是因为在acks为1和all时,适合的记录批次大小和生产者数量不同。因此下次我们将再次进行Producer的调整,保持acks为all。然后进行Consumer的调整,展示优化整个系统吞吐量的结果。
第七部分:Apache Kafka的性能验证(4):Producer的重新调整以及Consumer的调整结果。