在一些场景下,比如zookeeper部署在k8s上,或者使用域名连接zookeeper集群,当zookeeper集群中节点ip发生变化或者替换时,不通版本的zookeeper SDK对此处理不一样。
我们在测试环境中,使用go-zookeeper(https://github.com/go-zookeeper/zk/blob/master/conn.go)连接容器化的zookeeper集群,在运维人员对zookeeper进行滚动更新时,zookeeper节点的ip发生了变化,此时zookeeper集群是一个高可用状态,但是业务连接出现了问题,查看日志发现程序依然连接着原来的zookeeper ip,推测是因为连接zookeeper的初始化时,将这些ip存入了缓存中。但是我们使用的kafka 3.1.0版本连接同样的zookeeper集群,并没有收到任何影响,因此我们对zookeeper的连接过程进行分析:
首先是go-zookeeper(同事的截图):
发现当某个ip不可用时,直接从地址列表中随机取出一个ip进行重连。此时当zookeeper on k8s进行滚动更新时,地址列表中所有ip不可用,此时业务程序出现问题。
再来看kafka 3.1.0版本,使用的zookeeper SDK版本为3.6.3:
可以看到kafka会重新获取新的zookeeper节点ip建立连接。(老版本的zookeeper比如3.4.10的HostProvider.next()方法还是采用的初始化ip建立连接,这种情况下也会出现像go一样的问题)