问题现象
我们发现kafka生产环境。开启了SASL认证后,Kafka客户端访问Kafka Server,执行简单的Topic list命令,平均时间需要20秒左右。
直接连接Kafka集群里面的Zookeeper后,发现访问zookeeper也需要很久。
并且存在,有的节点访问很快,1秒就返回了。有的需要很慢,40秒左右。
又发现,只要kafka客户端和服务端是同一个网段的,就访问很快,秒级响应
如果客户端和kafka服务端在不同的网段,则需要20秒左右或者更久,或者直接超时了。
搜索引擎一搜,发现很多类似的问题,但是都没有给出解决方案,都说Kafka开启SASL认证后,
第一次连接都需要20秒左右。但是同网段的秒回,又怎么解释呢,说不通啊。
排查过程
抓包
想看哪里耗时,直接使用tcpdump抓包看了。比对了同网段和不同网段的通信过程,发现都一样。
可以发现,在TCP握手成功后,要开始Kafka的认证过程时,这一步骤花费了20秒。
从网络通信判断确实是认证过程比较耗费时间。那具体是在哪一个过程耗费时间呢。
开启Kafka debug日志
想确认具体是哪里耗时,看日志嘛,方便后续定位源码。
可以看到从初始化连接到HANDSHAKE_OR_VERSION_REQUEST很慢。
不同网段的日志:
后面的报错,是因为命令执行结束了,客户端关闭了连接。
同网段的日志。发现同一个处理流程,不到一秒就处理完了。
源码排查
看日志,耗时主要是在认证类中的实现 SaslServerAuthenticator
看了请求状态,日志中出现的HAND_OR_VERSIONS_REQUEST是在INITIAL_REQUEST后面。
看源码,再请求转到这个HAND_OR_VERSIONS_REQUEST状态前,只有这一段才有可能造成了延时。毕竟涉及网络IO,需要读取数据。
再往下深究
发现TransportLayer底层是用了InetAddressSocket创建Socket连接。
这个时候,就开始怀疑是不是DNS域名解析的问题,毕竟这个InetAddressSocket就是干这个的。
难道Kafka将IP地址当成了域名? 如果域名解析很慢,就造成了整体卡慢。
因为同网段不需要域名解析。不同网段才需要解析啊。
问题短暂解决(过了一天又出现问题)
修改Kafka配置,将暴露给外部访问的listener,改成域名的方式
然后在客户端本机Host文件配置域名解析规则:
/etc/hosts
10.109.223.3 node3
然后再执行上述的命令,也可以达到秒级返回了。
如图,跨网段访问,10秒内返回了。(过了一天又出现卡慢了)
只需要在客户端本机配置HOST
真正的问题
还是跟域名有关。Kafka客户端配置了域名解析服务器。所以客户端发出的请求,会先经过域名解析服务器。这就很耗费时间了。
最终查看 /etc/resolv.conf
确实配置了nameserver。
最终将nameserver都去掉,之前客户端配置的/etc/hosts 新添加的域名解析也去掉,问题最终解决。
search localdomain
nameserver 8.8.8.8
nameserver 114.114.114.114