2020年笔者在做微服务部件升级时,Dubbo的注册中心从Zookeeper切换到Nacos碰到个问题,最近刷Github又有网友提到类似的问题,就在这篇文章里做个梳理和总结。

1、问题描述

前几年我在做微服务部件升级时,将Dubbo的注册中心从Zookeeper切换到Nacos。切换的原因是有2点:

  • Zookeeper保障了CP,面对大量服务上下线时,吞吐量和响应有瓶颈。Nacos保障了AP,目前微服务的场景下,业界建议优先保障AP,这样有较好的吞吐量和较快的响应。
  • 本着能少用部件就少用,尽量减少故障点的原则。Nacos既可以做注册中心也可以做配置中心,所以二合一,只采用一个部件。

切换完之后,奇怪的事情发生了,出现2个现象:

  • 有些微服务启动很慢很慢,甚至长达15分钟的时间都无法成功启动,一直在打印大量的nacos请求日志。但是有些微服务启动又较快。
  • 通过VisualVM查看JVM的线程情况,发现有的微服务居然高达4000左右的线程数。但是没切换之前只有几百的线程数。启动了大量的线程,导致CPU飙升不少,同时服务启动也慢。

2、通过现象开始排查

出现这种问题时,刚开始有点抓瞎,但是我们只能从常规的手段一点点排查,急不来。通过表面的现象,我们来逐步分析。

现象一:微服务启动很慢很慢,一直在打印大量的nacos请求日志。日志如下:

现象二:JVM的线程数高达4000左右。线程情况如下:

基于以上现象,我们只能初步判断是nacos的问题(当然结论不是nacos的问题)。

我们先才猜测:可能由于某种原因,产生了大量的nacos线程,每个线程又在不停的发送http请求。

那接下来继续分析Nacos。

3、分析Nacos

回顾Nacos原理

我们知道Nacos客户端注册和订阅服务流程大概如下:

所以,一般nacos-client有4个重要线程:

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

分析Nacos

根据以上线程的名称和原理流程图,我们可以在nacos源码里找到对应的位置,代码如下:

翻看每个线程里执行的任务,确实能找到他们都在向nacos-server发送对应的的http的api请求:

既然找到了创建线程和发起http调用的原因,那就继续查看是哪里调用的。

此时会自然想到dubbo了,因为dubbo采用nacos作为注册中心,自然要依赖nacos-client创建出nacos注册中心相关的类,然后从中获取到微服务的元数据信息。

4、Dubbo登场

在翻看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参数:

至此问题的原因已经找到了,接下来就是如何解决了。

5、解决方法

解决方法也很简单,就是在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&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的2.7.8版本出现的,最后通过将2.7.9的修复class替换了2.7.8的NacosRegistryFactoryclass类,然后重新打了dubbo依赖包,问题得以解决。

有朋友会问:为啥不是引用2.7.9呢?因为我担心2.7.9有其他问题,所以做个class替换,然后继续用2.7.8是个较好的方式。

6、总结

本文主要梳理了Dubbo使用Nacos注册中心的坑,同时也讲述了,出现问题时,如何一步一步排查。透过现象结合源码,逐步找到问题的真相。

当然在排查之前,就需要对Dubbo和Nacos有一定的了解。所以各位朋友,在平时还是要多积累,多深入原理,这样遇到问题才能顺利解决。

本篇完结!欢迎点赞 关注 收藏!!!

原文链接:https://mp.weixin.qq.com/s/r4O4d2gAwA8LfJ1Ir98nmg

======>>>>>> 关于我 <<<<<<======

深度剖析:Dubbo使用Nacos注册中心的坑的更多相关文章

  1. Spring Cloud 系列之 Alibaba Nacos 注册中心(一)

    前言 从本章节开始,我们学习 Spring Cloud Alibaba 相关微服务组件. Spring Cloud Alibaba 介绍 Spring Cloud Alibaba 致力于提供微服务开发 ...

  2. SpringCloud Alibaba实战(7:nacos注册中心管理微服务)

    源码地址:https://gitee.com/fighter3/eshop-project.git 持续更新中-- 在上一节我们已经完成了Nacos Server的本地部署,这一节我们学习如何将Nac ...

  3. Nacos注册中心之概要设计

    本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star. 前言 在之前的文章中分析了Nacos配置中心,配置中心的核心是配置的创建.读取.推送. 注册中 ...

  4. Nacos注册中心和配置中心流程原理

    一.Nacos注册中心 1.服务启动后---->服务注册原理 springCloud集成Nacos实现原理: 服务启动时,在spring-cloud-commons包下 spring.facto ...

  5. dubbo支持的注册中心

    dubbo支持的注册中心 Dubbo提供的注册中心有如下几种类型可供选择: Multicast注册中心 Zookeeper注册中心 Redis注册中心 Simple注册中心 ZooKeeper是一个开 ...

  6. 80%面试官不知道的dubbo → 【redis注册中心】

    dubbo的redis注册中心配置和注意事项 配置provider和consumer项目的pom.xml,增加如下2个依赖: org.apache.commons commons-pool2 2.4. ...

  7. Spring Cloud Alibaba 使用nacos 注册中心

    ### 背景 上一文我们讲到了如何去搭建注册中心,这一次我们讲述如何使用nacos作为注册中心 ### spring-cloud-alibaba-basis 创建基础依赖 首先我们创建一个spring ...

  8. Spring Cloud 系列之 Alibaba Nacos 注册中心(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Alibaba Nacos 注册中心(一) 本篇文章讲解 Nacos 注册中心集群环境搭建. Nacos 集群环境搭建 ...

  9. 手动造轮子——为Ocelot集成Nacos注册中心

    前言     近期在看博客的时候或者在群里看聊天的时候,发现很多都提到了Ocelot网关的问题.我之前也研究过一点,网关本身是一种通用的解决方案,主要的工作就是拦截请求统一处理,比如认证.授权.熔断. ...

  10. Spring Cloud Alibaba(4)---Nacos(注册中心)

    Nacos(注册中心) 有关Spring Cloud Alibaba之前写过三篇文章. Spring Cloud Alibaba(1)---入门篇 Spring Cloud Alibaba(2)--- ...

随机推荐

  1. 【LeetCode二叉树#05】平衡二叉树

    力扣题目链接(opens new window)](https://leetcode.cn/problems/balanced-binary-tree/) 给定一个二叉树,判断它是否是高度平衡的二叉树 ...

  2. Html飞机大战(十四): 分数编辑和生命值设定

    好家伙,这章让我感受到了面向对象的优势了   1.分数设置 每个种类的敌机分数都设置好了, 那么当我们击毁不同的敌机后,加上不同的分数就行了 但是我们还是要想一下,   我要在哪里放这个分数增加的方法 ...

  3. jvm调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    目录 前言 jps(Java Virtual Machine Process Status Tool) jstack jmap(Memory Map)和jhat(Java Heap Analysis ...

  4. 【Azure 云服务】如果云服务证书过期会有什么影响,证书时间应该如何查看

    问题描述 如果云服务证书过期会有什么影响,证书时间应该如何查看 问题答案 在云服务中,有两种证书:服务证书 和 管理证书 什么是服务证书? 通过浏览器访问云服务中的服务(Web Role)时候所使用的 ...

  5. 【Azure 事件中心】在Azure Function App中消费Event Hub数据,时常出现EventReceiveError

    问题描述 在Azure Function App中消费Event Hub数据,时常出现EventReceiveError:New receiver 'P3-00122a562-4fa4-7f3f-ad ...

  6. [Linux] Linux 自动挂载mount --bind 实现类似目录硬链的效果 (包含ZFS方案)

    说明 这个命令用以将一个目录挂载到另一个目录,以实现类似于硬链的操作 但是这个命令只是在内存中建立了一个映射,重启系统之后挂载就消失了 而linux是不支持目录硬链的,具体原因见linux为什么不能硬 ...

  7. 10 个解放双手的 IDEA插件,少些冤枉代码(第三弹)

    大家好,我是小富- 好久没发这种实用贴了,最近用到了一些能提升工作效率的IDEA插件,给小伙伴们分享一下.相信我,我分享的这些插件,都是实实在在能解决实际开发场景中痛处的. 以往的两篇IDEA插件分享 ...

  8. Editor - Goto Location: Multiple Definitions - vscode 多个定义,直接跳转到主定义 不进行选择

    Editor - Goto Location: Multiple Definitions - vscode 多个定义,直接跳转到主定义 不进行选择 配置里面 搜 多

  9. 五大基础dp

    动规条件 • 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构, 即满足最优化原理. • 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响.也就是说,某状 ...

  10. 面试官:小伙子,能聊明白JMM给你SSP!我:嘚吧嘚吧一万字,直接征服面试官!

    写在开头 面试官:小伙子,JMM了解吗? 我:JMM(Java Memory Model),Java内存模型呀,学过的! 面试官:那能给我详细的聊一聊吗,越详细越好! 我:嗯~,确定越详细越好?起码得 ...