前言
众所周知,Kafka是一个开源分布式事件流平台,尤其以高吞吐、低延迟著称,并且已经被数千家企业用于高性能数据管道、流分析、数据集成和核心业务应用程序。
实际生产环境中,由于每个现场的网络环境各有差异,经常遇到业务方反馈生产或者消费Kafka性能问题。通常需要现场排查Kafka服务状态、主机资源、业务程序日志、Broker日志等。如果均未见异常,那就需要使用抓包工具深挖现场的网络环境。本文描述完整的抓包分析案例总结,并基于现场案例详细描述抓包工具的妙用。
工欲善其事必先利其器,网络问题必须安排上抓包工具tcpdump和界面化分析工具wireshark。
1. tcpdump简介
用于抓取linux服务器数据包。如果未安装,需要自行安装,如下:
[root@felixzh ~]# yum install tcpdump
[root@felixzh ~]# tcpdump -h
常见用法如下:
监听网络接口
tcpdump -i eth0 #不指定,默认监视第一个网络接口
监听 某主机 发送 和 接收 的 数据包
tcpdump -i eth0 host felixzh2
监听 某主机 发送的 数据包
tcpdump -i eth0 src host felixzh2
监听 某主机 接收的 数据包
tcpdump -i eth0 dst host felixzh2
监听 访问本机端口 的数据包
tcpdump -i eth0 port 9092
监听 某主机 与 本地端口 的数据包
tcpdump -i eth0 host felixzh2 and port 9092
根据mac地址进行抓包
tcpdump -i eth0 ether src 0c:da:41:1d:57:57
# ether:指icmp协议中没有源ip和目的ip,所以需要依赖于ether 协议。
# src 0c:da:41:1d:57:57 :是指源mac地址为:0c:da:41:1d:57:57
2. wireshark用法
用于界面化分析tcpdump抓取的数据包。如果未安装,需要自行安装。
注意:最新版本需要WIN10操作系统。下载地址为:
https://www.wireshark.org/download.html
wireshark支持Kafka协议:编辑->首选项->Protocols->Kafka,如下:
Kafka版本3.7.0。为方便测试,开发Producer工具,已上传github:
https://github.com/felixzh2020/felixzh-learning-kafka/tree/master/SendMaxMessage
支持指定消息大小、消息总数、消息发送方式、所有producer参数。
步骤1:启动Kafka3.7.0、创建test topic
[root@felixzh bin]# ./kafka-topics.sh --bootstrap-server felixzh:9092 --topic test --partitions 1 --replication-factor 1 --create
步骤2:启动tcpdump开始抓包
[root@felixzh bin]# tcpdump -i eth0 host felixzh1 and port 9092 -vv -w res.cap
上述命令表示监听网卡eth0,主机名felixzh1,端口9092数据包。
步骤3:idea设置conf.properties相关参数、启动Main方法
版本3.7.0日志给出了INFO级别的提示信息:Node 0 disconnected。而有些旧版本并不会提供上述信息,仅仅会提供一些DEBUG级别信息。这类提示信息很容易被没有经验的人忽略!
步骤4:ctrl+c停止tcpdump,使用wireshark分析数据包文件res.cap
可以看到tcp三次握手建立连接的过程,如下:
可以看到ApiVersions请求和Metadata请求的过程,如下:
最后可以看到客户端发送Produce请求之后,Kafka直接触发四次挥手关闭链接,如下:
所以,可以看出是Kafka端主动关闭了Produce端连接。
其实详细查阅Kafka日志,INFO日志也是可以看到蛛丝马迹的,如下:
[2024-04-22 20:10:43,515] INFO [KafkaApi-0] Closing connection due to error during produce request with correlation id 4 from client id producer-1 with ack=0
Topic and partition to exceptions: test-0 -> org.apache.kafka.common.errors.RecordBatchTooLargeException (kafka.server.KafkaApis)
上述日志对应到源码,可以看出Kafka服务端确实closeConnection。从源码来看,即使acks=0,Kafka对Produce请求还是会抛异常的。
服务端之所以出现RecordBatchTooLargeException异常是因为Produce请求携带的数据大小超过服务端配置message.max.bytes。
至此,一个使用抓包工具排查网络问题的完整真实案例完成!
上述案例实践相对简单,本章节以一个复杂的现场案例详细描述抓包工具举足轻重的作用。公安行业某地市局点反馈,业务方写Kafka集群性能很差,部分组网架构类似于下图:
业务方在Produce客户端抓包发现收到大量RST报文。业务方认为是Kafka服务异常,频繁关闭tcp连接,导致每次发送数据都需要新建连接、性能开销大、写性能降低。如下:
说明:手头没物理防火墙,以nmap关闭tcp连接模拟测试,命令如下:
[root@felixzh bin]# nmap -sT -O felixzh2 -p 53044 --scanflags RST
现场排查Kafka服务状态、主机资源、业务程序日志、Broker日志均未见异常。那怎么办呢?很直观的想法:服务端也抓包分析,来个当面对质。
Kafka服务端数据包显示,确实有大量三次握手触发建立tcp连接。但是,服务端并未发送过RST报文(异常重置)和FIN报文(正常关闭),如下:
最终,问题聚焦到防火墙。防火墙厂商排查发现TCP空闲超过设置过小!
其实,Kafka服务端对空闲tcp连接也有超时关闭机制,超时参数如下:
connections.max.idle.ms
Linux操作系统对空闲tcp连接也有超时关闭机制,参数如下:
$ sysctl -a | grep keepalive
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
通过抓包工具tcpdump和界面化分析工具wireshark,可以很方便的排查现场网络问题!