1 调优Kafka的目标
通常来说,任何系统调优的目标都是为了满足系统常见的非功能性需求,而性能则是众多非功能性需求中最重要的一个。
不同的系统对性能的侧重点不同,DB的话性能是响应时间,而对于Kafka等MQ来说,则意味着吞吐量和延时。
所谓吞吐量,也称TPS,它指的是Broker端进程或Client端应用程序每秒能处理的字节数或消息数,这个值越大越好。
所谓延时,和响应时间类似,它指的是从Producer端发送消息到Broker端持久化完成之间的时间间隔。这个指标也可以代表端到端的演示,即我们从Producer端发送消息到Broker端持久化再到Consumer端消费消息成功的总时间间隔。和TPS相反,这个值越小越好。
2 性能优化漏斗
在调优过程中,业界有一个所谓的优化漏斗的模型,我们可以在每一层进行对应的优化调整,层级越靠上,调优效果越明显。
(1)应用程序层
指优化Kafka客户端应用程序代码,比如:合理使用数据结构、缓存计算开销大的运算结果等。该层优化的效果最明显,也比较简单。
(2)框架层
指合理设置Kafka集群的各种参数。改源码不容易,改参数还是So Easy。
(3)JVM层
Kafka Broker是一个普通的JVM进程,对JVM的优化对Kafka Broker也是适用的。
(4)操作系统层
对操作系统的优化虽然重要,但是效果可能不如想象中那么好,且学习投入相对较大。
3 基础性调优
操作系统层
4个关键点:
(1)挂载文件系统时禁掉atime更新;
atime 的全称是 access time,记录的是文件最后被访问的时间。记录 atime 需要操作系统访问 inode 资源,而禁掉 atime 可以避免 inode 访问时间的写入操作,减少文件系统的写操作数。
mount -o noatime
(2)选择ext4或XFS文件系统;
尤其是 XFS 文件系统,它具有高性能、高伸缩性等特点,特别适用于生产服务器。
(3)swap空间的设置;
建议将 swappiness 设置成一个很小的值,比如 1~10 之间,以防止 Linux 的 OOM Killer 开启随意杀掉进程。此外,建议将vm.max_map_count设置为一个较大的值,避免在一个主题数超多的Broker机器上碰到 OutOfMemoryError:Map failed的严重错误。
vim /etc/sysctl.conf 增加 vm.swappiness=N 增加 vm.max_map_count=655360 执行 sysctl -p 让sysctl.conf的修改生效
(4)页缓存大小;
给Kafka预留的页缓存越大越好,最小值至少要容纳一个日志段的大小,也就是Broker端参数log.segment.bytes的值,该值默认为1GB。预留出一个日志段大小,至少能保证 Kafka 可以将整个日志段全部放入页缓存,这样,消费者程序在消费时能直接命中页缓存,从而避免昂贵的物理磁盘 I/O 操作。
JVM层
2个关键点:
(1)堆设置
建议将JVM堆大小设置为6~8GB,在众多实际生产环境中,这个大小已被证明是非常合适的。
(2)GC收集器
建议使用 G1 收集器,主要原因是方便省事,至少比 CMS 收集器的优化难度小得多。另外,一定要尽力避免 Full GC 的出现。如果 Kafka 环境中经常出现 Full GC,可以配置 JVM 参数 -XX:+PrintAdaptiveSizePolicy,来探查一下到底是谁导致的 Full GC。
框架层(Broker端)
最关键的一点:保持服务器端和客户端版本一致!因为,如果不保持一致,可能会导致Kafka丧失一些性能收益,比如Zero Copy零拷贝。
另外的关键点就是合理设置Broker端的参数,毕竟源码修改不易,改参数还是so easy的。这一部分,后面性能指标调优部分详细介绍。
应用层
3个关键点:
(1)不要频繁地创建Producer和Consumer对象实例;
构造这些对象的开销很大,能复用就复用。
(2)用完及时关闭;
这些对象底层会创建较多的物理资源,不及时关闭,可能会造成资源泄露。
(3)合理利用多线程改善性能;
4 性能指标调优
调优吞吐量
在实际环境中,用户似乎总是愿意用较小的延时增加的代价,去换取 TPS 的显著提升。毕竟,从 2ms 到 10ms 的延时增加通常是可以忍受的。事实上,Kafka Producer 就是采取了这样的设计思想。
这里重点说说 Broker 端参数 num.replica.fetchers ,它表示的是 Follower 副本用多少个线程来拉取消息,默认使用 1 个线程。
如果你的 Broker 端 CPU 资源很充足,不妨适当调大该参数值,加快 Follower 副本的同步速度。因为在实际生产环境中,配置了 acks=all 的 Producer 程序吞吐量被拖累的首要因素,就是副本同步性能。增加这个值后,你通常可以看到 Producer 端程序的吞吐量增加。
其他的,具体可以参考上一篇《吞吐量与消息可靠性的实践》。
调优延时
下面的表格展示了优化延时的一些参数设置:
可以看到,优化延时其实与消息的高可靠性传递是违背的。
这里重点说说在 Consumer 端的参数 fetch.min.bytes,它表示只要 Broker 端有能返回的数据(根据配置的bytes数决定)就立即令其返回给 Consumer,缩短 Consumer 消费延时。这里将其设置为1,表示只要Broker端积攒了1字节数据,就可以返回给Consumer端。但是,这个1字节实在是太小了,还是让Broker端一次性积攒多一点点再返回给Consumer吧。
5 总结
本文总结了Kafka调优的目的和方法论,并直接给出了调优Kafka的关键参数配置,可以直接用于生产环境。
参考资料
极客时间,胡夕《Kafka核心技术与实战》
B站,尚硅谷《Kafka 3.x入门到精通教程》