0. 背景
dubbo 2.7.5,最近发现 zk 的 node 越来越多,监控报警半夜给我打电话。后来排查发现是业务方使用泛化调用不规范!
但是排查过程学习到了很多。
1. 监控
线上 zk 监控主要是监控 zk 的 node 数量,以及机器 cpu memory,报警主要是 zk 的 node 数量报警,到了阈值。
2. 排查
先查看在报警前后的 zk snapshot 文件有什么变化,将 zk 快照文件转译为文本:
java -cp ../../zookeeper-3.4.8.jar:../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.b0008ebdd > 05141102.txt
这样你就得到了两份 snapshot,一份是报警前一段时间,正常的快照 node,一份是报警后的快照 node。
3. Dubbo 节点规则
/dubbo/{com.xx.Service}/consumers/consumer%3A%2F%2F{ip.ip.ip.ip}%2Forg.apache.dubbo.rpc.service.GenericService%3Fapplication%3D{app-name}%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.0.2%26generic%3Dtrue%26interface%3D{com.xx.Service}%26lazy%3Dfalse%26loadbalance%3Drandom%26pid%3D26879%26release%3D2.7.3.5-ext%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1620959181596
/dubbo/服务提供者接口/consumers/泛化接口?timestamp=
通过搜索 zk 报警之后的快照文件发现有接近3000个泛化调用统一接口
接口查看该 node 的 ephemeralOwner,定位到该业务服务,同时查看线上该业务服务的发布记录,发现该业务服务的线上发布时间和故障报警时间重合:当该服务重启发布的时候,报警消失,猜测应该是因为机器重启,临时泛化节点都下掉。后来定位代码,发现泛化调用后没有显示的调用 .destory() 销毁泛化调用的 node!
4. 解决
- 泛化调用后,finally 块代码加入 reference.destory() 方法。
- 通过内存缓存 GenericService genericService = reference.get() 获得的 GenericService 类。
- 不用泛化调用,直接调用。