springboot启动dubbo客户端连接服务端过程

article/2025/11/7 19:22:39

前言

如果我问你,dubbo客户端启动的时候是如何连接服务器端的?这个过程比较复杂,今天我们一起学习起来~

本文分以下几个部分

1、springboot启动dubbo需要配置

2、初始化@Reference过程

3、小结

一、项目应用

1、引入jar包

<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version>
</dependency>
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-dependencies-zookeeper</artifactId><version>${dubbo.version}</version><type>pom</type><exclusions><exclusion><artifactId>log4j</artifactId><groupId>log4j</groupId></exclusion><exclusion><artifactId>slf4j-log4j12</artifactId><groupId>org.slf4j</groupId></exclusion></exclusions>
</dependency>

2、项目配置

@EnableDubbo(scanBasePackages = "com.XXX")

EnableDubbo标签包含两个子标签

@EnableDubboConfig
@DubboComponentScan

2.1、@EnableDubboConfig

@EnableDubboConfig标签的处理器是DubboConfigConfigurationRegistrar。处理器基本做了以下几个步骤

1、获取EnableDubboConfig类的注解

2、读EnableDubboConfig注解的字段multiple=true

3、DubboConfigConfiguration.Single.class

解析DubboConfigConfiguration.Single.class,并注入spring容器管理

解析DubboConfigConfiguration.Multiple.class,并注入spring容器管理

4、注入以下bean到spring容器中

        ReferenceAnnotationBeanPostProcessor

        DubboConfigAliasPostProcessor

        DubboApplicationListenerRegistrar

        DubboConfigDefaultPropertyValueBeanPostProcessor

        DubboConfigEarlyRegistrationPostProcessor

        DubboConfigEarlyInitializationPostProcessor

        由于本文重点分析springboot启动dubbo客户端连接服务端过程。接下来我们重点关注ReferenceAnnotationBeanPostProcessor。该类继承了AbstractAnnotationBeanPostProcessor。而AbstractAnnotationBeanPostProcessor类会解析@Reference标签,

        

        要想解析@Reference标签,一共分两步骤

        ①、初始化@Reference标签到spring容器

        ②、走dubbo中@Reference业务类。也就是DubboBootstrap类的业务逻辑。

三、初始化@Reference标签到spring容器

3.1、applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

在创建bean的时候调用栈会调到

AbstractAnnotationBeanPostProcessor#buildAnnotatedMetadata。

将字段和方法的标签包装成AnnotatedInjectionMetadata对象

private AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {Collection<AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);Collection<AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);return new AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
}

AbstractAnnotationBeanPostProcessor#findInjectionMetadata会会缓存类名称和metadata的对应关系

this.injectionMetadataCache.put(cacheKey, metadata);

继续缓存到InjectionMetadata里面的checkedElements字段

this.checkedElements = checkedElements;

3.2、populateBean(beanName, mbd, instanceWrapper);

populateBean负责填充Bean实例属性,最终在populateBean会调用到ReferenceAnnotationBeanPostProcessor#doGetInjectedBean。

        1、构建referencedBeanName

        例如ServiceBean:com.opay.online.push.provider.facade.DingTalkPushFacade

该名称会缓存到referencedBeanNameIdx字段中

        2、构建referenceBeanName

        例如:@Reference com.opay.online.push.provider.facade.DingTalkPushFacade

        3、缓存referencedBeanName到referencedBeanNameIdx

        4、构建ReferenceBean对象

        5、缓存InjectedElement和ReferenceBean关系到injectedFieldReferenceBeanCache (针对字段)

        6、referenceBean.get()

        该方法涉及很多方面,我们重点关注本文的重点,就是如何对外发起连接的。

                6.1、构建名称是registry的InterfaceCompatibleRegistryProtocol对象

invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));

        注意dubbo spi文件的该对应关系:registry=org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryProtocol

        6.2、构建QosProtocolWrapper对象

        6.3、构建MockClusterWrapper对象

        6.4、构建consumerUrl

        6.5、构建MigrationInvoker对象

        6.6、调用org.apache.dubbo.registry.client.migration.MigrationRuleListener#onRefer

        6.7、zk注册,将该接口对应的providers,configurators,routers都按照节点的形式注册到zk当中去。调用栈和方法如下。

 public void doRegister(URL url) {try {zkClient.create(toUrlPath(url), url.getParameter(DYNAMIC_KEY, true));} catch (Throwable e) {throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);}}

        6.8、调用QosProtocolWrapper的refer方法

        6.9、调用ProtocolFilterWrapper的refer方法

        6.10、调用dubbo父类的refer方法

public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {return new AsyncToSyncInvoker<>(protocolBindingRefer(type, url));}

        6.11、dubboProtocol调用getClients(url)

 client = Exchangers.connect(url, requestHandler);

        6.12、调用HeaderExchanger#connect

return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);

6.13、调用Transporters#connect

 public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException {if (url == null) {throw new IllegalArgumentException("url == null");}ChannelHandler handler;if (handlers == null || handlers.length == 0) {handler = new ChannelHandlerAdapter();} else if (handlers.length == 1) {handler = handlers[0];} else {handler = new ChannelHandlerDispatcher(handlers);}return getTransporter().connect(url, handler);}

        6.14、调用NettyTransporter的connect方法

 return new NettyClient(url, handler);

        仔细看nettyClient初始化会发现,该方法会直接让客户端和服务器端进行了一次连接

public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {super(url, handler);// set default needReconnect true when channel is not connectedneedReconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, true);initExecutor(url);try {doOpen();} catch (Throwable t) {close();throw new RemotingException(url.toInetSocketAddress(), null,"Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()+ " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t);}try {// connect.connect();if (logger.isInfoEnabled()) {logger.info("Start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress() + " connect to the server " + getRemoteAddress());}} catch (RemotingException t) {if (url.getParameter(Constants.CHECK_KEY, true)) {close();throw t;} else {logger.warn("Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()+ " connect to the server " + getRemoteAddress() + " (check == false, ignore and retry later!), cause: " + t.getMessage(), t);}} catch (Throwable t) {close();throw new RemotingException(url.toInetSocketAddress(), null,"Failed to start " + getClass().getSimpleName() + " " + NetUtils.getLocalAddress()+ " connect to the server " + getRemoteAddress() + ", cause: " + t.getMessage(), t);}}

最后我打印了整个发送连接的调用栈,供大家参考阅读

四、小结

        dubbo在springboot环境启动的过程中,用#Reference引用类对象要经过dubbo加载对服务器端进行一个长链接。本文仔细分析了dubbo在springboot启动的过程中是如何一步一步对外进行连接的。大概来说要分以下几步:

        1、dubbo实现接口AbstractAnnotationBeanPostProcessor,在类加载过程中能够感知ReferenceAnnotationBeanPostProcessor,解析@DubboReference, @Reference注解,然后走doGetInjectedBean方法做referenceBean.get()。

        2、referenceBean.get()做了很多事情,本文关注的是其启动客户端和服务器端连接过程。在创建代理invoker的时候经过Exchanger层-》Transporters层,最终发送了连接请求到远程服务提供方。



http://chatgpt.dhexx.cn/article/9AkAWHT0.shtml

相关文章

dubbo实现原理机制

Dubbo的总体架构如图所示&#xff1a; 框架分层架构中&#xff0c;各个层次的设计要点&#xff1a; 服务接口层&#xff08;Service&#xff09;&#xff1a;该层是与实际业务逻辑相关的&#xff0c;根据服务提供方和服务消费方的业务设计对应的接口和实现。 配置层&#xff0…

Dubbo源码分析(三):Dubbo之服务端(Service)

如上图所示的Dubbo的暴露服务的过程&#xff0c;不难看出它也和消费者端很像&#xff0c;也需要一个像reference的对象来维护service关联的所有对象及其属性&#xff0c;这里的reference就是provider。由于ServiceBean实现了 &#xfeff;&#xfeff; InitializingBean接口&am…

Dubbo——初识RPC、Dubbo框架、使用直连方式实现Dubbo

文章目录&#xff1a; 1.RPC & 软件架构 1.1 单一应用架构 1.2 分布式微服务架构 1.3 RPC 2.Dubbo概述 2.1基本架构 2.2 dubbo支持的协议 3.直连方式实现dubbo 3.1 服务提供者的创建 3.2 服务消费者的创建 3.3 启动测试&#xff01;&#xff01;&#xff01; 1.…

分布式基本理解与Dubbo基本概念

学习dubbo之前&#xff0c;先要了解一下什么是分布式 分布式基础理论 什么是分布式系统 分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统。 随着互联网的发展&#xff0c;网站应用的规模不断扩大&#xff0c;常规的垂直应用架构已无法…

Dubbo的原理和机制

Dubbo :是一个RPC框架&#xff0c;SOA框架&#xff1a; Dubbo缺省协议采用单一长连接和NIO异步通讯&#xff0c;适合于小数据量大并发的服务调用&#xff0c;以及服务消费者机器数远大于服务提供者机器数的情况。 作为RPC&#xff1a;支持各种传输协议&#xff0c;如dubbo,hes…

dubbo实现原理介绍

一、什么是dubbo Dubbo是Alibaba开源的分布式服务框架&#xff0c;它最大的特点是按照分层的方式来架构&#xff0c;使用这种方式可以使各个层之间解耦合&#xff08;或者最大限度地松耦合&#xff09;。从服务模型的角度来看&#xff0c; Dubbo采用的是一种非常简单的模型…

Dubbo-聊聊Dubbo协议

前言 Dubbo源码阅读分享系列文章&#xff0c;欢迎大家关注点赞 SPI实现部分 Dubbo-SPI机制 Dubbo-Adaptive实现原理 Dubbo-Activate实现原理 Dubbo SPI-Wrapper 注册中心 Dubbo-聊聊注册中心的设计 Dubbo-时间轮设计 通信 Dubbo-聊聊通信模块设计 什么是协议 在网…

dubbo客户端的实现

业界微服务大行其道。服务与服务之间的同学主要有有以下两大类。 阿里RPC框架&#xff1a;dubboRestFull风格的Http调用 我们知道Http接口我们找到PostMan这种Http客户端。 但是dubbo似乎并没有想关的客户端&#xff0c;我们调试的时常常需要同时打开两个以上的服务。 dubbo是…

dubbo组成原理-http服务消费端如何调用

dubbo协议已经用的很多了&#xff0c;这里来稍微介绍一下http协议&#xff0c;官方对http协议的说明简直少的让人发指。哈哈 百度大部分都只是讲了http服务端的配置 那就先从服务端的配置说起 dubbo需要的jar包这里就不说明了&#xff0c;网上找些maven的pom就可以 web.xml…

Dubbo基本原理机制

分布式服务框架&#xff1a; –高性能和透明化的RPC远程服务调用方案–SOA服务治理方案 -Apache MINA 框架基于Reactor模型通信框架&#xff0c;基于tcp长连接 Dubbo缺省协议采用单一长连接和NIO异步通讯&#xff0c;适合于小数据量大并发的服务调用&#xff0c;以及服务消费…

Dubbo基本原理与机制

1、什么是Dubbo Dubbo 是一款高性能、轻量级的开源 RPC 框架&#xff0c;提供服务自动注册、自动发现等高效服务治理方案&#xff0c; 可以和 Spring 框架无缝集成。 2、Dubbo依赖关系 1、服务消费者&#xff08;Consumer&#xff09;: 调用远程服务的服务消费方&#xff0c…

dubbo原理和机制

Dubbo 框架是用来处理分布式系统中&#xff0c;服务发现与注册以及调用问题的&#xff0c;并且管理调用过程。 一&#xff0c;工作流程&#xff1a; 服务提供者在启动的时候&#xff0c;会通过读取一些配置将服务实例化。Proxy 封装服务调用接口&#xff0c;方便调用者调用。…

Dubbo的原理与机制

​ Dubbo 前言 在介绍Dubbo之前先了解一下基本概念&#xff1a; Dubbo是一个RPC框架&#xff0c;RPC&#xff0c;即Remote Procedure Call&#xff08;远程过程调用&#xff09;&#xff0c;相对的就是本地过程调用&#xff0c;在分布式架构之前的单体应用架构和垂直应用架…

Dubbo基础及原理机制

1. 什么是Dubbo&#xff1f; Dubbo是 阿里巴巴公司开源的一个高性能RPC 分布式服务框架&#xff0c;使得应用可通过高性能的 RPC 实现服务的输出和输入功能&#xff0c;可以和 Spring框架无缝集成&#xff0c;现已成为 Apache 基金会孵化项目。 2. 为什么要用Dubbo&#xff1…

Dubbo原理和机制详解(非常全面)

Dubbo是一款Java RPC框架&#xff0c;致力于提供高性能的RPC远程服务调用方案。Dubbo 作为主流的微服务框架之一&#xff0c;为开发人员带来了非常多的便利。 本文我们重点详解 Dubbo 的原理机制 mikechen 目录 Dubbo核心功能Dubbo核心组件Dubbo的架构设计Dubbo调用流程 1️…

大地测量学基础(复习)第一部分

写在前面 这篇博文是用来复习课程“大地测量学基础”的&#xff0c;里面仅列出本人觉得这门课程比较重要的部分&#xff0c;希望能够帮助到有需要的朋友。 课本采用《大地测量学基础》孔祥元&#xff0c;武汉大学出版社。 前面已经有一篇“大地测量学基础&#xff08;复习&…

深入理解ArcGIS的地理坐标系、大地坐标系

1、引言 地理坐标&#xff1a;为球面坐标。 参考平面地是 椭球面,坐标单位:经纬度 大地坐标&#xff1a;为平面坐标。参考平面地是 水平面,坐标单位&#xff1a;米、千米等 地理坐标转换到大地坐标的过程可理解为投影。 &#xff08;投影&#xff1a;将不规则的地球曲面转…

GNSS定位中的不同高度概念及计算

文章目录 高度相关的几个基本概念RTKLIB中高度设置与计算参考文献 由于在GNSS定位中由多种高度表示&#xff0c;不同的高度概念很容易混淆&#xff0c;中英文对应有时候也容易搞混。因此整理了一下常用的两种高度——椭球高、正高的概念与计算&#xff0c;并且标注了对应的英文…

概念讲解:大地水准面 | 地球椭球体 | 参考椭球体 | 大地基准面 | 地图投影

文章目录 大地水准面地球椭球体参考椭球体大地基准面地图投影几个概念之间的关系相关文章 大地水准面 指平均海平面通过大陆延伸勾画出的一个连续的封闭曲面。大地水准面包围的球体称为大地球体。从大地水准面起算的陆地高度&#xff0c;称为绝对高度或海拔。 大地水准面是对地…

地图学的基础知识_天文坐标系_大地坐标系_地心坐标系及其相关概念

学习地图学&#xff0c;由于地理知识欠缺&#xff0c;学习相关投影知识还为时过早&#xff0c;需要复习一些基本概念。 阅读对象:测绘类 地球自然球体: 由地球自然表面所包围的的形体称为地球自然体。 地球自然球体形状:地球不是一个正球体&#xff0c;而是一个极半径略短&a…