首页 > 编程语言 >Dubbo源码解析-Provider端监听注册中心动态配置原理

Dubbo源码解析-Provider端监听注册中心动态配置原理

时间:2024-04-04 10:59:36浏览次数:32  
标签:Dubbo URL url 源码 notify Provider override 服务端

上篇我们介绍了provider服务暴露源码,地址如下

Dubbo源码解析-Provider服务暴露Export源码解析_dubbo exporter-CSDN博客

        本文主要针Dubbo服务端注册中心节点,实现动态配置变更原理,从dubbo源码角度进行解析。

        Dubbo 服务端动态配置原理比较简单,也是面试过程中比较常问的技术问题,大家可以好好仔细读一下本文。有疑问欢迎留言。

        接着说明,读Dubbo源码最好是先对Spring源码有一定的了解。如果大家需要,我也可以针对Spring框架做一系列源码的解读专栏。

         不过不用担心,如果需要Spring的源码知识,文章中也会进行Spring源码铺垫介绍的。

        如果内容中有没描述清楚的,或者大家在阅读源代码有疑问的,欢迎留言,看到就会及时回复。

        为了更清楚的分析解释源码,源代码中部分不重要的内容可能会删减,保留重要内容方便大家理解。

        我们知道,Dubbo对每个服务的配置,会写入到服务节点对应的configurators节点,在服务端服务启动后,会注册监听时间,来监听/dubbo/com.*.*/configurators/节点变更。从而实现动态刷新本地服务配置功能。具体过程我们接下来详细介绍一下。

主要内容

  • 服务端什么时候订阅的
  • 服务端订阅事件做了什么

服务端如何订阅的

        Dubbo对每个服务的配置,会写入到服务节点对应的configurators节点,在服务端服务启动后,会注册监听时间,来监听/dubbo/com.*.*/configurators/节点变更。具体流程可以参考Dubbo源码解析-Provider服务暴露Export源码解析_dubbo exporter-CSDN博客

服务端订阅事件

        服务端在启动的过程中建立了一个notify的映射关系CuratorWatch.press->ChildListener.childChange()->AbstractRegistry.notify()。完成override事件对主机属性的覆盖和对客户端代理的生成。

流程概述:

  1. verride协议中修改或者添加的属性合并到originUrl中,生成新的URL
  2. 比较新的URL和当前URL是否相同
  3. 不相同则重新完成服务暴露:其实就是创建一个新的DubboExport对象。
  4. 服务端只做了一件事,根据新的URL,创建新的DubboExport对象。

具体流程

  1. CuratorWatc.precess调用到ChildListener.childChanged()
  2. AbstractRegistry.notify(URL url, NotifyListener listener, List<URL> urls).url:provider协议URL,urls为empty协议或者override协议地址:configurators节点下的
    1. 遍历urls
    2. 判断和url是否匹配,主要是判断目录是否相等
    3. result = new HashMap<String, List<URL>>().创建新的目录和override的list的映射
    4. 覆盖notified全局变量,ConcurrentMap<URL, Map<String, List<URL>>>prividerUrl和configurators和override映射
    5. .saveProperties(url):保存本地文件,把override协议列表保存到本地缓存文件
      1. 文件properties,key为服务名称,value为空格分割的orverride协议地址
      2. 文件地址:用户目录+/.dubbo/dubbo-registry-应用名称—服务地址.cache
      3. 保存文件的目的:服务在启动的时候可以优先从本地加载。AbstractRegistry构造函数中调用
        1. loadProperties():加载缓存文件中的override配置,不需要zookeeper也可以完成属性覆盖
        2. notify(url.getBackupUrls()):触发覆盖
    6. listener.notify(categoryList):调用overrideListener,privider端口,则只修改dubboExport
      1. 将override的URL集合,专为List<Configurator>
      2. 获取dubbo协议地址
        1. URL originUrl = RegistryProtocol.this.getProviderUrl(invoker);
      3. 当前dubboURL
        1. URL currentUrl = exporter.getInvoker().getUrl();
      4. 把override协议中的属性合并到dubbo协议中Configurator中
        1. URL newUrl = getConfigedInvokerUrl(configurators, originUrl);
      5. 如果当前url和新url不同,则重新创建DubboExport对象,持有inoker执行链,invoker中有新的url
        1. RegistryProtocol.this.doChangeLocalExport(originInvoker, newUrl);

         总结:

  1. verride协议中修改或者添加的属性合并到originUrl中,生成新的URL
  2. 比较新的URL和当前URL是否相同
  3. 不相同则重新完成服务暴露:其实就是创建一个新的DubboExport对象。

                
      Override,Configurators在服务端触发
                    .notify方法,服务端只做了一件事,根据新的URL,创建新的DubboExport对象。
 

源码解析

1.AbstractRegistry.notify

protected void notify(URL url, NotifyListener listener, List<URL> urls) {
        
        Map<String, List<URL>> result = new HashMap<String, List<URL>>();
        for (URL u : urls) {
            //主要是判断目录是否相等
            if (UrlUtils.isMatch(url, u)) {
                String category = u.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
                List<URL> categoryList = result.get(category);
                if (categoryList == null) {
                    categoryList = new ArrayList<URL>();
                    //创建新的目录和override的list的映射
                    result.put(category, categoryList);
                }
                categoryList.add(u);
            }
        }
        if (result.size() == 0) {
            return;
        }
        //获取缓存中的override协议的list
        Map<String, List<URL>> categoryNotified = notified.get(url);
        if (categoryNotified == null) {
            notified.putIfAbsent(url, new ConcurrentHashMap<String, List<URL>>());
            categoryNotified = notified.get(url);
        }
        for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
            String category = entry.getKey();
            List<URL> categoryList = entry.getValue();
            //覆盖notified缓存中的
            categoryNotified.put(category, categoryList);
            //把override协议列表保存到本地缓存文件中
            saveProperties(url);
            //事件触发核心
            listener.notify(categoryList);
        }
    }

2.RegistryProtocol.OverrideListener.Notify

public synchronized void notify(List<URL> urls) {
            

            //根据覆盖override url生成Configurator对象
            List<Configurator> configurators = RegistryDirectory.toConfigurators(matchedUrls);

            
            //The origin invoker
            URL originUrl = RegistryProtocol.this.getProviderUrl(invoker);
            String key = getCacheKey(originInvoker);
            ExporterChangeableWrapper<?> exporter = bounds.get(key);
            if (exporter == null) {
                logger.warn(new IllegalStateException("error state, exporter should not be null"));
                return;
            }
            //The current, may have been merged many times
            URL currentUrl = exporter.getInvoker().getUrl();
            //Merged with this configuration
            //把override协议中修改或者添加的属性合并到originUrl中
            URL newUrl = getConfigedInvokerUrl(configurators, originUrl);
            //如果新旧url不相等
            if (!currentUrl.equals(newUrl)) {
                //这里URL对象改了,需要重新创建DubboExporter对象,覆盖之前的那个对象
                RegistryProtocol.this.doChangeLocalExport(originInvoker, newUrl);
                logger.info("exported provider url changed, origin url: " + originUrl + ", old export url: " + currentUrl + ", new export url: " + newUrl);
            }
        }

总结:上面内容中,每个从业务流程和源码角度进行了详细分析,如果大家有疑问或者对文章排版任何方面有建议都可以留言评论,看到都会及时回复大家。

知识总结,分享不易,全文手敲,欢迎大家关注点赞评论收藏。

标签:Dubbo,URL,url,源码,notify,Provider,override,服务端
From: https://blog.csdn.net/u014336799/article/details/137356891

相关文章

  • SpringBoot医院信管系统设计与实现毕设(文档+源码)
            目录一、项目介绍二、开发环境三、功能介绍四、核心代码五、效果图六、源码获取:        大家好呀,我是一个混迹在java圈的码农。今天要和大家分享的是一款基于SpringBoot大学生体质测试管理系统,项目源码请点击文章末尾联系我哦~目前有各类成......
  • 计算机毕业设计选题之SSM网上书城系统【源码+PPT+文档+包运行成功+部署讲解】
    ......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-13 acl - ip权限
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12729 1重点关注1.1本节内容通过schema为ip的方式设置权限,只有指定ip才能操作 1.2关键代码//ip方式的aclList<ACL>aclsIP=newArrayList<ACL>();......
  • 中间件 ZK分布式专题与Dubbo微服务入门 6-12 acl -自定义用户权限
    0课程地址https://coding.imooc.com/lesson/201.html#mid=12728 1重点关注1.1本节内容通过schema为digest密文的形式设置用户权限,调用权限 1.2关键代码//自定义用户认证访问List<ACL>acls=newArrayList<ACL>();......
  • 常见面试题--动态规划介绍(附C++源码实现)
    关注我,持续分享逻辑思维&管理思维;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;有意找工作的同学,请参考博主的原创:《面试官心得--面试前应该如何准备》,《面试官心得--面试时如何进行自我介绍》, 《做好面试准备,迎接2024金三银四》。【图解《程序员面试常见的十大算法......
  • dubbo 统一异常处理
    依赖包pom.xml如下:<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-registry-nacos</artifactId><version>3.0.4</version></dependency>dubbo服务:示例:@DubboService(interfaceClass=......
  • Java最短路径算法知识点(含面试大厂题和源码)
    最短路径算法是计算机科学和图论中的核心问题之一,它旨在找到从一个顶点到另一个顶点或在所有顶点之间的最短路径。这个问题在多种实际应用中都非常重要,如网络路由、交通规划、社交网络分析等。以下是一些与最短路径算法相关的知识点:Dijkstra算法:由荷兰计算机科学家艾兹......
  • Java归并排序知识点(含面试大厂题和源码)
    归并排序是一种有效的排序算法,采用分治法(DivideandConquer)策略。它将数组分成两半,对每一半递归地进行排序,然后将两个有序的半部分合并成一个整体的有序数组。归并排序在最坏情况、平均情况和最好情况下都保持(O(n\logn))的时间复杂度,是一种稳定的排序算法。由于其分而治......
  • Java快速排序知识点(含面试大厂题含源码)
    快速排序是一种高效的排序算法,由C.A.R.Hoare在1960年提出。它的基本思想是分而治之(DivideandConquer)。快速排序的关键在于选取一个“基准值”(pivot),然后将数组分为两个子数组:一个包含所有小于基准值的元素,另一个包含所有大于基准值的元素。这个过程称为“分区”(partitio......
  • java毕业设计二手书籍拍卖小程序[附源码]
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义选题背景:随着数字化时代的深入发展,人们对于信息的获取和物品的交易方式正经历着翻天覆地的变化。特别是在教育领域,电子书的普及使得纸质书籍逐渐被边缘化,这并不意......