通过本文能学习什么?
- 初步了解zookeeper监控
- 如何运用tcpdump + Wireshark抓包分析
- Dubbo在zookeeper上节点设计
- 如何查看zookeeper节点快照
背景
zookeeper作为dubbo的注册中心,承载着服务的基础信息(方法名,分组,版本等),服务关系等信息。随着业务增多,服务数增加,注册中心的网络IO已逐步成为瓶颈。
介绍zookeeper监控
zookeeper3.4.6后提供四字命令可以查看zookeeper集群状态信息。
例如:
- echo conf | nc localhost 2181,查看集群配置信息,端口,最大连接数等
- echo cons | nc localhost 2181,查看客户端链接的详情,接受/发送包数,session id等
- echo crst | nc localhost 2181,重置所有客户端的统计信息
- echo dump | nc localhost 2181,列出未经处理的会话和临时节点
- echo envi | nc localhost 2181,查看服务器的环境信息,java.home,os.name等
- echo ruok | nc localhost 2181,测试集群是否正常运行
- echo srst | nc localhost 2181,重置服务器的统计信息
- echo srvr | nc localhost 2181,查看服务器的详细信息。zk版本、接收/发送的包数量、连接数、运行模式、节点总数等
- echo stat | nc localhost 2181,查看客户端列表,接收/发送包数量、连接数、运行模式、节点总数、延迟等
- echo wchs | nc localhost 2181,查看watches相关信息
- echo mntr | nc localhost 2181,列出集群的健康状态。接受/发送的包数量、操作延迟、运行模式、节点总数、watch总数、临时节点总数等
我们使用Grafana和Prometheus去收集zookeeper集群信息和展示,底层也是通过四字命令获取信息。
线上案例
我们线上zookeeper监控偶尔会收到堆积请求数告警,经查看发现是网络IO过大造成了请求堆积,不过很快又恢复了,可能某个应用那一刻爬去了大量zookeeper节点。
排查过程
如何找到调用方?
由于突发流量是不定时的,没法通过实时流量分析,只能通过侧面突破。
zookeeper上存储的都是服务的基本信息。服务的摘挂流量,重启等操作都会导致zookeeper节点变动,并通知上游。这样就可以通过发布系统,找下那一段时间谁在发布,看看是否有突破口。
通过查看发布系统,找到了A服务的网络IO与zookeeper的网络IO图形契合,并且出入口流量也能对上,至此,我们找到了谁在大量拉取zookeeper.
zookeeper哪些节点被频繁拉取?
初步怀疑是A服务使用dubbo方式不对,最后查看A服务源码,并未找到问题。
由于A服务每次重启都会导致zookeeper流量增高,说明是可复现的,可以进行抓包分析,抓包工具主流的就是tcpdump + Wireshark。
tcpdump是linux下的网络截取工具,是服务端抓包的首选。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来过滤信息。通过以下命令获取我们需要的数据包。
tcpdump host (10.10.xx.xx or 10.10.xx.xx or 10.10.xx.xx) and tcp port 4181 -s 0 -w zk.pcap
host:指定多个IP
port:指定端口
-s 0:抓取完整包,而不是默认的68字节
-w:保存文件
还有很多其他参数,大家可以通过man tcpdump查看。
我们用Wireshark打开zk.pcap抓包文件。Wireshark十分强大,可以分析TCP等各种协议,并且提供丰富的语法来过滤信息,分析TCP三次握手就能通过Wireshark查看,大家有兴趣可以下来研究。
我们发现请求了非常多的/dubbo/com.missfresh.algo.common.api.service.IRecoRecallService/configurators节点。
节点作用是什么?
简单介绍下dubbo在zookeeper注册节点作用。
routes节点:路由规则相关,永久节点。
configurators节点:dubbo配置相关,永久节点。
providers节点:服务提供者信息,临时节点,生产者注册到该节点,消费者会监听该节点。
consumers节点:消费者信息,临时节点,消费者注册到该节点。
configurators节点记录了服务的IP,分组和版本信息。如果有N个IP,M个分组,K个版本,那个该节点个数为N * M * K个。
如何查看zookeeper上该节点个数?
可以通过zkClient连上集群查看。今天我们通过另一种方式,分析zookeeper快照日志查看。
zookeeper有事务日志(log.*)和快照日志(snapshot.*),可以通过zookeeper自带工具把snapshot日志转成文本。
java -classpath :./slf4j-api-1.7.25.jar:../zookeeper-3.4.12.jar org.apache.zookeeper.server.SnapshotFormatter ~/Documents/snapshot.b3c8cb285 > ~/Documents/zk-snapshot-20200325.log
通过本地文件分析,发现该节点接近4000个。
总结
总结原因
1、由于dubbo服务的上下线,调节权重等操作都会生成configurators永久节点,导致该节点一直积累,每次服务启动都会去拉取该服务的所有配置,导致zookeeper出口流量增加。
2、为什么会有这么多节点?业务方在使用时存在问题,每次迭代都升级服务版本号,正确做法是尽量兼容低版本的服务,只有在完全无法兼容情况再考虑升级服务版本号。并且给每个上游一个service group,但并没有通过service group隔离环境/机器,导致节点数是服务版本号与service group的乘积。
解决方案
1、拿到废弃节点后,通过zkClient删除废弃节点。
2、业务调整服务调用方式,把service group去掉,改用多个方法对外暴露。
未来规划
随着业务逐渐往docker迁移,我们基础组件也迎来新的挑战,频繁的扩容缩容,IP变换也会导致注册中心越来越臃肿,需要一个注册中心治理服务给他瘦身。