小记一次Kafka集群响应慢问题追查

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小记一次Kafka集群响应慢问题追查相关的知识,希望对你有一定的参考价值。

参考技术A 某一天业务来找我,反映发数据到某一个Kafka集群特别慢。
并且他们提供了一份自己的测试结果,结果显示发送数据到Kafka集群A的平均响应延迟在10ms以内,但是发送到Kafka集群B的平均响应延迟却达到了2000ms+。
这种问题一般是比较头疼的,首先,我们Kafka集群都有监控和报警,通过查看可用性、流量变化、Kafka日志等方式,都没有发现任何异样;其次,响应慢也有可能和用户的使用方式和测试方法有关系。
因此第一步,我决定验证一下问题的存在。

在 kafka/bin 目录中,kafka提供了一个写请求性能测试脚本 kafka-producer-perf-test.sh 。
这个脚本会运行kafka中的 kafka.perf.ProducerPerformance 类,发送消息到kafka并输出CSV报告。
测试命令如下:

kafka/bin/kafka-producer-perf-test.sh --broker-list $BROKER_LIST --topics perf-test-topic --show-detailed-stats --messages 10000 --csv-reporter-enabled --metrics-dir ./perf-report

通过分析生成的报告,发现确实有一台节点的响应比较慢:

可以看到P999分布已经达到了1300ms左右,这显然是不正常的,但是原因是什么呢?

既然日志没有问题,那只能看一下jstack信息了:

如上发现jstack中有非常奇怪的信息,很多kafka-request-handler线程都处于阻塞状态。
这里简单解释一下kafka的处理请求线程模型,引用一篇讲 Kafka NIO网络通信的文章 中的图来说明:

如图,kafka采用了Java NIO中的selector模型。一个Acceptor线程负责接受请求,多个Processor线程负责处理请求。但实际上Processor线程只是把请求封装成kafka request,然后丢到RequestChannel中(当然也负责读取response并返回,这里不展开)。真正执行请求的是KafkaRequestHandler,即jstack中的kafka-request-handler线程。
所以当kafka-request-handler线程出现大量阻塞的时候,会极大地影响整个节点的响应效率。

关于Java线程中的BLOCKED状态,可以直接看一下Java doc说明:

可见kafka-request-handler线程是因为抢锁而发生了阻塞。我们根据jstack信息中的 kafka.cluster.Partition.appendMessagesToLeader 定位到了源码:

可以看到这个方法确实是同步的,同步对象是leaderIsrUpdateLock。由于leaderIsrUpdateLock是 kafka.cluster.Partition 的成员变量,也就是说只有在写同一个topic partition的时候,才会发生互斥等待。
所以发生上面问题的原因只可能是某个topic有大量的写请求,而且这个topic的partition数量不多,导致并发不足。
于是大量该topic的ProduceRequest占用了kafka-request-handler线程池,但是这些线程之间互相抢锁,执行效率比较低,从而导致其他topic的请求无法及时被处理。

通过分析日志和查看监控流量,定位到集群中某个topic的ProduceRequest请求的QPS占了整个集群的80%以上。
通过查看该topic监控指标中的单位时间内的消息条目数(MessagesInPerSec)和单位时间内的发送请求数(ProduceRequestPerSec),可以计算出该Topic平均不到10条消息就会触发一次kafka写请求;再考虑到partition数量,推测应该是业务采用了kafka producer的同步模式,每条消息都触发一次kafka写请求。
解决方法有两种:

当然,增加topic partition数量也能在一定程度上缓解问题,因为不同partition之间的写请求是不互斥的,但这种方式更像是治标不治本,掩盖了根本问题。

合理地发送网络请求在分布式系统中非常重要,为了提高效率,通常在权衡时效性和吞吐的情况下,以“聚少为多”的方式发送批量的请求。过多的小请求不仅会降低吞吐,还可能会压垮后端的服务。
当然,作为服务提供方,需要通过多租户、限流等方式,避免不正常使用的场景把服务压垮。

kafka与zookeeper管理之kafka-manager踩坑小记

      在elk集群搭建过程中,为了极大程度的利用服务器资源,kafka、zookeeper、logstash规划混跑在了同一组服务器上。随着业务量的增加,要频繁增加调整kafka的topic,出现问题时还要去服务器敲命令查看kafka和zookeeper的相关信息,效率低而且不方便,于是就考虑到用kafka的管理工具kafka-manager,安装配好后,整个集群的状态一目了然,而且可以方便的进行topic的操作、消费情况的查询、broker各种状态指标的查询等,非常方便,各种信息一目了然,安装配置过程中遇到两坑做下记录,先看下安装后的信息展示:.....

......

浏览全部请点击运维网咖社地址:kafka与zookeeper管理之kafka-manager踩坑小记

本文出自 “奔跑的linux” 博客,请务必保留此出处http://benpaozhe.blog.51cto.com/10239098/1932654

以上是关于小记一次Kafka集群响应慢问题追查的主要内容,如果未能解决你的问题,请参考以下文章

troubleshooting记一次Kafka集群重启导致消息重复消费问题处理记录

kafka部署遇到的问题

Reactive Spring实战 -- 响应式Kafka交互

阿里云服务器部署zookeeper集群+kafka集群

Kafka单节点至集群的安装部署及注意事项

ELK采集MySQL慢日志实现