前几年我在做微服务部件升级时,将Dubbo的注册中心从Zookeeper切换到Nacos。切换的原因是有2点:
切换完之后,奇怪的事情发生了,出现2个现象:
出现这种问题时,刚开始有点抓瞎,但是我们只能从常规的手段一点点排查,急不来。通过表面的现象,我们来逐步分析。
现象一:微服务启动很慢很慢,一直在打印大量的nacos请求日志。日志如下:
现象二:JVM的线程数高达4000左右。线程情况如下:
基于以上现象,我们只能初步判断是nacos的问题(当然结论不是nacos的问题)。
我们先来猜测:可能由于某种原因,产生了大量的nacos线程,每个线程又在不停的发送http请求。
那接下来继续分析Nacos。
我们知道Nacos客户端注册和订阅服务流程大概如下:
所以,一般nacos-client有4个重要线程:
根据以上线程的名称和原理流程图,我们可以在nacos源码里找到对应的位置,代码如下:
翻看每个线程里执行的任务,确实能找到他们都在向nacos-server发送对应的的http的api请求:
既然找到了创建线程和发起http调用的原因,那就继续查看是哪里调用的init方法。
此时会自然想到dubbo了,因为dubbo采用nacos作为注册中心,自然要依赖nacos-client创建出nacos注册中心相关的类,然后从nacos注册中心类中获取到微服务的元数据信息。
在翻看Dubbo源码之前,先回顾下Dubbo是怎样基于 引用配置文件 或者 引用配置注解创建Proxy的,大致流程如下:
ReferenceAnnotationBeanPostProcessor#doGetInjectedBean
⏬
ReferenceAnnotationBeanPostProcessor#buildReferenceBeanIfAbsent
⏬
ReferenceBeanBuilder#build
⏬
ReferenceBean#afterPropertiesSet
⏬
ReferenceConfig#init
至此完成了referenceProxy的创建。
重点看ReferenceConfig#init方法,方法里有一行代码:ref = createProxy(map);,顺着这行代码往里走,如下:
RegistryProtocol#refer
⏬
AbstractRegistryFactory#getRegistry
重点来了,重点来了,重点来了,核心代码和注释见下图。
总之是:因为在上面ReferenceConfig#init方法里引入了timestamp参数,同时又因为NacosRegistryFactory又自己实现了一套createRegistryCacheKey方法,这个方法里没有截掉timestamp参数,所有就会导致从缓存里取不到注册中心信息,所有就会不停的去创建,从而又创建了更多的线程,从而发送了很多http请求。
再次查看ReferenceConfig#init方法的源码,确实是加入了timestamp参数:
至此问题的原因已经找到了,接下来就是如何解决了。
解决方法也很简单,就是在Dubbo的NacosRegistryFactory类里面截掉timestamp参数。
遗憾的是,我当时发现了这个问题时,打算给Dubbo官方发issue的,发现已经有网友抢先一步发了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×tamp=17125458564892.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的2.7.8版本出现的,最后通过将2.7.9的修复class替换了2.7.8的NacosRegistryFactoryclass类,然后重新打了dubbo依赖包,问题得以解决。
有朋友会问:为啥不是引用2.7.9呢?因为我担心2.7.9有其他问题,所以做个class替换,然后继续用2.7.8是个较好的方式。
本文主要梳理了Dubbo使用Nacos注册中心的坑,同时也讲述了,出现问题时,如何一步一步排查。透过现象结合源码,逐步找到问题的真相。
当然在排查之前,就需要对Dubbo和Nacos有一定的了解。所以各位朋友,在平时还是要多积累,多深入原理,这样遇到问题才能顺利解决。
本文链接:http://www.28at.com/showinfo-26-82749-0.html深度剖析:Dubbo使用Nacos注册中心的坑
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
下一篇: 深入理解C/C++指针的算术运算