dubbo 3.2.0 consumer bean初始化及服务发现简记

news2025/1/11 17:47:38

consumer bean初始化

以spring 如下配置
<dubbo:reference id="versionConsumerBean" interface="org.apache.dubbo.samples.version.api.VersionService" version="*"/>

为例,先使用spring 的初始化,核心代码

 try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

初始化为class org.apache.dubbo.config.spring.ReferenceBean。

然后在类似如下代码

VersionService versionService = (VersionService) context.getBean("versionConsumerBean");

处进行了二次变化,创建LazyProxy
在这里插入图片描述

核心代码在ReferenceBean的getObject,代码如下:
 /**
     * Create bean instance.
     *
     * <p></p>
     * Why we need a lazy proxy?
     *
     * <p/>
     * When Spring searches beans by type, if Spring cannot determine the type of a factory bean, it may try to initialize it.
     * The ReferenceBean is also a FactoryBean.
     * <br/>
     * (This has already been resolved by decorating the BeanDefinition: {@link DubboBeanDefinitionParser#configReferenceBean})
     *
     * <p/>
     * In addition, if some ReferenceBeans are dependent on beans that are initialized very early,
     * and dubbo config beans are not ready yet, there will be many unexpected problems if initializing the dubbo reference immediately.
     *
     * <p/>
     * When it is initialized, only a lazy proxy object will be created,
     * and dubbo reference-related resources will not be initialized.
     * <br/>
     * In this way, the influence of Spring is eliminated, and the dubbo configuration initialization is controllable.
     *
     *
     * @see DubboConfigBeanInitializer
     * @see ReferenceBeanManager#initReferenceBean(ReferenceBean)
     * @see DubboBeanDefinitionParser#configReferenceBean
     */
    @Override
    public T getObject() {
        if (lazyProxy == null) {
            createLazyProxy();
        }
        return (T) lazyProxy;
    }

变换后返回的是一个aop java对象了。
在这里插入图片描述

服务发现

dubbo 的服务调用是proxy通invoker实现,因此核心过程就在如下函数中。

@SuppressWarnings({"unchecked"})
private T createProxy(Map<String, String> referenceParameters) {
    urls.clear();

    meshModeHandleUrl(referenceParameters);

    if (StringUtils.isNotEmpty(url)) {
        // user specified URL, could be peer-to-peer address, or register center's address.
        parseUrl(referenceParameters);
    } else {
        // if protocols not in jvm checkRegistry
        aggregateUrlFromRegistry(referenceParameters);
    }
    createInvoker();

    if (logger.isInfoEnabled()) {
        logger.info("Referred dubbo service: [" + referenceParameters.get(INTERFACE_KEY) + "]." +
                (Boolean.parseBoolean(referenceParameters.get(GENERIC_KEY)) ?
                        " it's GenericService reference" : " it's not GenericService reference"));
    }

    URL consumerUrl = new ServiceConfigURL(CONSUMER_PROTOCOL, referenceParameters.get(REGISTER_IP_KEY), 0,
            referenceParameters.get(INTERFACE_KEY), referenceParameters);
    consumerUrl = consumerUrl.setScopeModel(getScopeModel());
    consumerUrl = consumerUrl.setServiceModel(consumerModel);
    MetadataUtils.publishServiceDefinition(consumerUrl, consumerModel.getServiceModel(), getApplicationModel());

    // create service proxy
    return (T) proxyFactory.getProxy(invoker, ProtocolUtils.isGeneric(generic));
}

在创建proxy的过程中,可以多次看到TargetService和protocolServiceKey的处理,核心是找到两者批量的service
在这里插入图片描述
核心批量比较代码如下

public static boolean isMatch(URL consumerUrl, URL providerUrl) {
    String consumerInterface = consumerUrl.getServiceInterface();
    String providerInterface = providerUrl.getServiceInterface();
    if (!"*".equals(consumerInterface) && !"*".equals(providerInterface) && !StringUtils.isEquals(consumerInterface, providerInterface)) {
        return false;
    } else if (!isMatchCategory(providerUrl.getCategory("providers"), consumerUrl.getCategory("providers"))) {
        return false;
    } else if (!providerUrl.getParameter("enabled", true) && !"*".equals(consumerUrl.getParameter("enabled"))) {
        return false;
    } else {
        String consumerGroup = consumerUrl.getGroup();
        String consumerVersion = consumerUrl.getVersion();
        String consumerClassifier = consumerUrl.getParameter("classifier", "*");
        String providerGroup = providerUrl.getGroup();
        String providerVersion = providerUrl.getVersion();
        String providerClassifier = providerUrl.getParameter("classifier", "*");
        boolean groupMatches = "*".equals(consumerGroup) || StringUtils.isEquals(consumerGroup, providerGroup) || StringUtils.isContains(consumerGroup, providerGroup);
        boolean versionMatches = "*".equals(consumerVersion) || StringUtils.isEquals(consumerVersion, providerVersion);
        boolean classifierMatches = consumerClassifier == null || "*".equals(consumerClassifier) || StringUtils.isEquals(consumerClassifier, providerClassifier);
        return groupMatches && versionMatches && classifierMatches;
    }
}

注意看最后几段boolean的match,即

  1. group
  2. version
  3. class(interface)

要匹配

invoker 是在服务发现后依次进行router-cluster-failover 判定后进行调用,可以参考下图

在这里插入图片描述
而服务发现(以zk为例),核心用到以下类
在这里插入图片描述

zk 数据结构

dubbo root

[zk: localhost:2181(CONNECTED) 23] ls /dubbo
[config, mapping, metadata, org.apache.dubbo.metadata.MetadataService, org.apache.dubbo.mock.api.MockService, org.apache.dubbo.samples.version.api.VersionService]

provider创建时候负责写入zk的providers


[zk: localhost:2181(CONNECTED) 24] ls /dubbo/org.apache.dubbo.samples.version.api.VersionService
[configurators, providers]

providers可以有多版本

[zk: localhost:2181(CONNECTED) 25] ls /dubbo/org.apache.dubbo.samples.version.api.VersionService/providers
[dubbo%3A%2F%2F192.168.3.28%3A20880%2Forg.apache.dubbo.samples.version.api.VersionService%3Fanyhost%3Dtrue%26application%3Dversion-provider%26background%3Dfalse%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26executor-management-mode%3Disolation%26file-cache%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.samples.version.api.VersionService%26methods%3DsayHello%26pid%3D8804%26prefer.serialization%3Dfastjson2%2Chessian2%26release%3D3.2.0%26revision%3D1.0.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1685160190088%26token%3Db4d3e756-3a85-40ab-b3fd-c4b1352879ce%26version%3D1.0.0, dubbo%3A%2F%2F192.168.3.28%3A20880%2Forg.apache.dubbo.samples.version.api.VersionService%3Fanyhost%3Dtrue%26application%3Dversion-provider%26background%3Dfalse%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26executor-management-mode%3Disolation%26file-cache%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.samples.version.api.VersionService%26methods%3DsayHello%26pid%3D8804%26prefer.serialization%3Dfastjson2%2Chessian2%26release%3D3.2.0%26revision%3D2.0.0%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1685160186753%26token%3Dbc2534d5-f980-4a41-ab90-e4e9ae688ad9%26version%3D2.0.0]

完整的service下目录

[zk: localhost:2181(CONNECTED) 7] ls -s /dubbo/org.apache.dubbo.samples.version.api.VersionService
[configurators, consumers, providers, routers]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/578409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EDR(端点、端点检测与响应中心、可视化展现)

EDR基本原理与框架 EDR定义 端点检测和响应是一种主动式端点安全解决方案&#xff0c;通过记录终端与网络事件&#xff08;例如用户&#xff0c;文件&#xff0c;进程&#xff0c;注册表&#xff0c;内存和网络事件&#xff09;&#xff0c;并将这些信息本地存储在端点或集中数…

C#,码海拾贝(26)——求解“一般带状线性方程组banded linear equations”之C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> /…

Redis五大基本数据结构(原理)

一、 Redis数据结构-String String是Redis中最常见的数据存储类型&#xff1a; 其基本编码方式是RAW&#xff0c;基于简单动态字符串&#xff08;SDS&#xff09;实现&#xff0c;存储上限为512mb。 如果存储的SDS长度小于44字节&#xff0c;则会采用EMBSTR编码&#xff0c;…

c++ 11标准模板(STL) std::map(六)

定义于头文件<map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class map;(1)namespace pmr { template <class Key, class T, clas…

优化器| SGD/SGD-m/SGD-NAG/Adagrad/Adadelta/RMSProp/Adam/Nadam/Adamax

前言&#xff1a;最近准备复习一下深度学习的基础知识&#xff0c;开个专栏记录自己的学习笔记 各种SGD和Adam优化器整理 基本概念 优化&#xff1a;最大化或最小化目标函数&#xff0c;具体指最小化代价函数或损失函数 损失函数 J(θ)f(hθ(x)&#xff0c;y)&#xff0c;h…

软考A计划-试题模拟含答案解析-卷五

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Android 12.0仿ios的hotseat效果修改hotseat样式

1.概述 最近在12.0产品项目需求的需要,系统原生Launcher的布局样式很一般,所以需要重新设计ui对布局样式做调整,产品在看到 ios的hotseat效果觉得特别美观,所以要仿ios一样不需要横屏铺满的效果 居中显示就行了,所以就要看hotseat的具体布局显示了 效果图如下: 2.仿io…

《Spring Guides系列学习》guide51 - guide55

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gui…

网络设备的部署(串行与并行)

串行设备 1.防火墙&#xff1a;能够实现区域隔离和访问控制 2.IPS(入侵防御系统)&#xff1a;能够检测入侵行为并阻断 3.WAF&#xff08;上网行为管理设备&#xff09;&#xff1a;保障web应用的安全 4.上网行为管理设备&#xff1a;对用户上网行为进行控制 5.FC交换机&am…

【源码解析】SpringBoot使用Nacos配置中心和使用 @NacosValue 进行热更新

SpringBoot使用Nacos 引入依赖 <dependency><groupId>com.alibaba.boot</groupId><artifactId>nacos-config-spring-boot-starter</artifactId><version>0.2.12</version> </dependency>增加本地配置 nacos:config:server-…

通过 ChatGPT 制作一个短视频

图文&#xff0c;生成视频 当通过 ChatGPT 生成连贯的 prompt 时&#xff0c;除了连环画&#xff0c;我们理所当然还可能畅想更激进的场景——生成动画视频。目前 AIGC 社区确实在生成视频方面有一定的尝试。比如 Deforum 可以通过多条 prompt&#xff0c;配合具体的切换时间点…

Centos7中mysql安装配置

前提&#xff1a;先关闭防火墙或开启tcp的3306端口 1、查看服务器上是否有现成的安装包 yum list mysql* 2、去mysql官网的yum资源库找到对应的rpm文件的下载链接 确定系统版本 cat /etc/redhat-release 到mysql官网复制对应版本的资源下载链接 MySQL :: Download MySQL Yum…

chatgpt赋能python:Python长连接详解:优化用户体验和节约资源的有效方式

Python长连接详解&#xff1a;优化用户体验和节约资源的有效方式 Python语言具备多样性和灵活性&#xff0c;是内容和功能极其丰富的一种编程语言。对于网站或者应用程序的开发&#xff0c;在Python语言的基础上可以实现长连接&#xff0c;优化用户体验和节约资源&#xff0c;…

网站部署与上线(1)虚拟机

文章目录 .1 虚拟机简介2 虚拟机的安装 本章将搭建实例的生产环境&#xff0c;将所有的代码搭建在一台Linux服务器中&#xff0c;并且测试其能否正常运行。 使用远程服务器进行连接&#xff1b; 基本的Linux命令&#xff1b; 使用Nginx搭建Node.js服务器&#xff1b; 在服务器端…

Admin.NET管理系统(vue3等前后端分离)学习笔记--持续更新

我的学习笔记 - 9iAdmin.NET 欢迎学习交流&#xff08;一&#xff09;前端笔记1.1 关于.env的设置1.2 关于路由模式问题1.3 关于 vue.config.ts1.4 关于 打包&#xff08;pnpm run build&#xff09;溢出问题1.5 关于 打包&#xff08;pnpm run build&#xff09;后部署到IIS重…

你知道网速的发展史吗? 80年代的我们是这样上网的!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

C++:征服C指针:指针(一)

关于指针 1.看一个简单的程序&#xff0c;来接触下指针2. 常见疑问&#xff1a;指针就是地址&#xff0c;那么int的指针和double的指针有什么区别 了3. 常见疑问&#xff1a;指针运算4. 为什么存在奇怪的指针运算符5. 试图将数组作为函数的参数进行传递。6. 什么是空指针5.1 声…

怎样用一周时间研究 ChatGPT

我是怎样用一周时间研究 ChatGPT 的&#xff1f; 上周大概开了 20 多个会&#xff0c;其中有一些是见了觉得今年可能会比较活跃出手的机构&#xff0c;其余见的绝大多数是和 ChatGPT 相关。 我后面就以 ChatGPT 为例&#xff0c;讲下我是如何快速一周 cover 一个赛道的&#x…

GDB 基础使用与多进程调试

​ GDB 全称“GNU symbolic debugger”是 Linux 下常用的程序调试器&#xff0c;当下的 GDB 支持调试多种编程语言编写的程序&#xff0c;包括 C、C、Go、Objective-C、OpenCL、Ada 等。 01 GDB 基础调试 1.1 基础使用 安装工具 # 安装 gcc sudo yum install gcc # 安装 g s…

记录一次el-table动态添加删除列导致表格样式错误(或不聚集)问题

记录一次el-table动态添加删除列导致表格样式错误问题 需求背景出现的问题解决方案理论&#xff1a;在el-table中设置key值&#xff0c;重新赋值表格数据之后&#xff0c;更新key值&#xff0c;达到动态更新效果 需求背景 一个电商类商品管理平台&#xff08;类似shopify产品编…