问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深度剖析:Dubbo使用Nacos注册中心的坑

创作时间:
作者:
@小白创作中心

深度剖析:Dubbo使用Nacos注册中心的坑

引用
CSDN
1.
https://blog.csdn.net/baily_ycl/article/details/138177968

本文将深入剖析在将Dubbo的注册中心从Zookeeper切换到Nacos时遇到的一个典型问题。通过详细描述问题现象、排查过程、技术分析和最终解决方案,帮助读者理解Dubbo与Nacos的交互机制,并掌握在遇到类似问题时的处理方法。

1. 问题描述

几年前在进行微服务部件升级时,将Dubbo的注册中心从Zookeeper切换到Nacos。切换的原因主要有两点:

  • Zookeeper保障了CP,面对大量服务上下线时,吞吐量和响应有瓶颈。Nacos保障了AP,在当前微服务场景下,业界建议优先保障AP,以获得更好的吞吐量和响应速度。
  • 本着能少用部件就少用的原则,Nacos既可以做注册中心也可以做配置中心,因此选择二合一,只采用一个部件。

切换后出现了两个主要问题:

  • 部分微服务启动异常缓慢,甚至长达15分钟都无法成功启动,期间持续打印大量Nacos请求日志。而有些微服务启动则相对正常。
  • 通过VisualVM查看JVM线程情况时发现,某些微服务的线程数高达4000左右,远高于切换前的几百个线程数。这导致CPU使用率显著升高,同时服务启动速度变慢。

2. 通过现象开始排查

面对这些问题,只能从常规手段入手逐步排查。根据表面现象,初步判断是Nacos的问题(尽管最终结论并非如此)。

现象一:微服务启动缓慢,持续打印大量Nacos请求日志。日志示例如下:

现象二:JVM线程数异常增多,达到4000左右。线程情况如下:

基于以上现象,推测可能由于某种原因产生了大量Nacos线程,每个线程都在不停地发送HTTP请求。

3. 分析Nacos

回顾Nacos原理

Nacos客户端注册和订阅服务的基本流程包括:

  • 定时从Nacos服务器拉取服务信息的线程
  • 维持心跳的线程
  • 监听服务变更的线程
  • 推送本服务变更信息的线程

在Nacos源码中,可以找到这些线程的具体实现:

进一步分析发现,这些线程确实都在向Nacos服务器发送对应的HTTP API请求:

4. Dubbo登场

在深入分析Dubbo源码之前,先回顾Dubbo基于引用配置文件或注解创建Proxy的基本流程:

  1. ReferenceAnnotationBeanPostProcessor#doGetInjectedBean
  2. ReferenceAnnotationBeanPostProcessor#buildReferenceBeanIfAbsent
  3. ReferenceBeanBuilder#build
  4. ReferenceBean#afterPropertiesSet
  5. ReferenceConfig#init

重点分析ReferenceConfig#init方法,其中有一行关键代码:

ref = createProxy(map);

继续追踪该代码,发现:

  1. RegistryProtocol#refer
  2. AbstractRegistryFactory#getRegistry

核心问题出现在NacosRegistryFactory中,具体如下:

问题根源在于:

  • ReferenceConfig#init方法中引入了timestamp参数
  • NacosRegistryFactory实现的createRegistryCacheKey方法没有处理这个timestamp参数
  • 导致无法从缓存中获取注册中心信息,从而不断创建新的线程并发送HTTP请求

查看ReferenceConfig#init方法的源码,确实加入了timestamp参数:

5. 解决方法

解决方案很简单:在Dubbo的NacosRegistryFactory类中处理掉timestamp参数。

遗憾的是,作者发现这个问题时,已经有其他网友在Dubbo官方仓库提交了相关issue,并且该修复已经合并到2.7.9分支。

以下是修复前后URL处理的对比:

2.7.8版本:
nacos://10.20.1.13:8848,10.20.1.14:8848,10.20.1.15:8848/org.apache.dubbo.registry.RegistryService?application=ehome-cloud&application.version=1.0&dubbo=2.0.2&interface=org.apache.dubbo.registry.RegistryService&namespace=dev-jzj&owner=ehome-cloud-owner&pid=21335&qos.enable=false&release=2.7.8&timestamp=1712545856489

2.7.9版本:
nacos://10.20.1.13:8848,10.20.1.14:8848,10.20.1.15:8848/org.apache.dubbo.registry.RegistryService?namespace=dev-jzj

最终通过将Dubbo依赖包中的NacosRegistryFactory类替换为2.7.9版本的实现,问题得以解决。

6. 总结

本文详细梳理了Dubbo使用Nacos注册中心时遇到的一个典型问题,并展示了如何通过现象分析逐步找到问题本质的排查过程。这要求读者对Dubbo和Nacos有深入的理解。因此,平时积累技术知识、深入理解原理是非常必要的。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号