概述
1 从spring BeanDefinitionParser 解析开始 (给自己一小时一撸到底)
2 源码部分
BeanDefinitionParser --> org.apache.dubbo.config.spring.schema.DubboBeanDefinitionParser
--->构造函数定位 org.apache.dubbo.config.spring.schema.DubboNamespaceHandler#init
--->org.apache.dubbo.config.spring.ReferenceBean 解析xml 并将bean注入容器中
ReferenceBean 实现了 org.springframework.beans.factory.FactoryBean 工厂bean
--->注入时org.springframework.beans.factory.FactoryBean#getObject 来产生实际对象
org.apache.dubbo.config.ReferenceConfig#get 方法初始化引用
org.apache.dubbo.config.ReferenceConfig#init 跟进 --->ref = createProxy(map);
org.apache.dubbo.config.ReferenceConfig#createProxy 跟进 ---> 非点对点(user specified URL, could be peer-to-peer address)从注册中心获取组装--->assemble URL from register center's configuration
--->if protocols not injvm checkRegistry--->org.apache.dubbo.config.AbstractInterfaceConfig#loadRegistries 获取注册中心地址--->执行单个注册中心 urls.size() == 1 条件成立-->
--->执行 invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0)); ---->registry协议来注册消费者(consumer://),同时获取服务端信息(dubbo://)--->详细源码:
---->registry协议来注册消费者(consumer://)
---->org.apache.dubbo.registry.integration.RegistryProtocol#refer
--->org.apache.dubbo.registry.RegistryFactory#getRegistry zookeeper协议zkclient读取
--->引用xml配置了 group信息并且多余1个group--->getMergeableCluster 默认不会走(考虑多个注册中心情况)--->通常只有一个注册中心走到doRefer
---->org.apache.dubbo.registry.integration.RegistryProtocol#doRefer
---->使用(引用接口,zookeeper协议Url)构造注册目录(本身实现org.apache.dubbo.registry.NotifyListener是注册中心的监听者)
org.apache.dubbo.registry.integration.RegistryDirectory#RegistryDirectory
(serviceKey = org.apache.dubbo.registry.RegistryService, serviceType = com.nini.adonis.service.RichService)
以及refer携带的查询参数"side" -> "consumer" "register.ip" -> "172.16.208.141" (注册者==消费者) "release" -> "2.7.3" "dubbo" -> "2.0.2" "retries" -> "1"
"group" -> "STAGE" "application" -> "rec-experiment" "interface" -> "com.nini.adonis.service.RichService" "check" -> "false" "loadbalance" -> "random" "pid" -> "15795"
---->确定 自愈簇或者叫容错系统或者故障容许度("cluster" -> "failover")
---->org.apache.dubbo.registry.integration.RegistryDirectory#turnRegistryUrlToConsumerUrl
通过org.apache.dubbo.common.URLBuilder#from 将registry的URL 转换为 consumer的URL (overrideDirectoryUrl 和 directoryUrl)
path->org.apache.dubbo.registry.RegistryService protocol->zookeeper host->172.16.208.180:2181,172.16.208.181:2181,172.16.208.182
----> org.apache.dubbo.registry.integration.RegistryDirectory#setRegistry 配置注册中心 内部包含zkClient
----> subscribeUrl 生成订阅URL remove : "register.ip" -> "172.16.208.141" 设置 protocol = consumer
----> 构造注册目录内含的 registeredConsumerUrl 就是把 订阅URL 增加一个参数pair "category" -> "consumers" 类别域
----> 将消费者-注册到注册中心server端: org.apache.dubbo.registry.RegistryService#register(registeredConsumerUrl) url= "consumer://172.16.208.141/com.nini.adonis.service.RichService?
application=rec-experiment&category=consumers&check=false&cluster=failover&dubbo=2.0.2&group=STAGE&interface=com.nini.adonis.service.RichService&lazy=false&loadbalance=random
&methods=h5RichDualStreamNote,richByBatchNoteIds,richDualStreamNote&organization=xdk&owner=zw&pid=15795&release=2.7.3&retries=1&revision=1.0.0&side=consumer&sticky=false&timeout=3000×tamp=1603530609654&version=1.0.0"
---->org.apache.dubbo.registry.support.FailbackRegistry#doRegister 发送注册请求到server side, 完成注册
---->注册目录 设置路由链路
---->注册目录 执行订阅org.apache.dubbo.registry.integration.RegistryDirectory#subscribe 把 订阅URL 增加一个参数pair "category" -> "providers,configurators,routers" 类别域
---->将订阅-订阅到注册中心server端:org.apache.dubbo.registry.RegistryService#subscribe
---->org.apache.dubbo.registry.support.FailbackRegistry#subscribe
--->org.apache.dubbo.registry.support.FailbackRegistry#doSubscribe 发送订阅请求到zookeeper -->org.apache.dubbo.registry.zookeeper.ZookeeperRegistry#doSubscribe 根据url解析出三个订阅path,如下:
[providers,configurators,routers] = [/dubbo/com.nini.adonis.service.RichService/providers,/dubbo/com.nini.adonis.service.RichService/configurators,/dubbo/com.nini.adonis.service.RichService/routers]
三个path,分别调用 org.apache.dubbo.remoting.zookeeper.ZookeeperClient#create(java.lang.String, boolean) 和 org.apache.dubbo.remoting.zookeeper.ZookeeperClient#addChildListener(返回树节点-data即provider信息)
创建zk树和增加树枝监听(当 providers configurators routers 发生变化时,通知到client端即完成订阅的关键);
org.apache.dubbo.remoting.zookeeper.ZookeeperClient#addChildListener 返回提供服务的providers url 比如6个中的一个 PROD 和 STAGE,通过group等做 consumer和provider url的match
过滤后可能只剩下符合条件的provider urls 比如只保留了stage环境的URL 如下图
--->notify (org.apache.dubbo.registry.support.FailbackRegistry#notify)--->doNotify (org.apache.dubbo.registry.support.FailbackRegistry#doNotify)-->抽象通知框架-->
org.apache.dubbo.registry.support.AbstractRegistry#notify 归类(keep every provider's category) 如下
---->依次执行 RegistryDirectory 注册目录 notify 方法 通知参数: routers configurators providers 对应的URL(注意 empty协议没有实际用途if (EMPTY_PROTOCOL.equals(url.getProtocol())) { continue; })
---->对于providers org.apache.dubbo.registry.integration.RegistryDirectory#refreshOverrideAndInvoker
---->org.apache.dubbo.registry.integration.RegistryDirectory#refreshInvoker
---->org.apache.dubbo.registry.integration.RegistryDirectory#toInvokers 遍历每一个provider url 循环!
---> 通过SPI确认 协议 dubbo是与否有class实现 org.apache.dubbo.common.extension.ExtensionLoader#hasExtension
---> Merge url parameters. the order is: override > -D >Consumer > Provider
---> 链接1 key = 根据url确定唯一一个 key
---> enabled = true ---> 初始化客户端链接 Refer a remote service: org.apache.dubbo.rpc.Protocol#refer org.apache.dubbo.common.extension.ExtensionLoader[org.apache.dubbo.rpc.Protocol]
--->org.apache.dubbo.common.extension.ExtensionLoader#getExtension(name="dubbo")
--->DubboProtocal -->org.apache.dubbo.rpc.protocol.AbstractProtocol#refer-
--->org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#protocolBindingRefer
--->create rpc invoker.org.apache.dubbo.rpc.protocol.dubbo.DubboInvoker----> 执行构造方法参数
--->org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#getClients
--->useShareConnect = true(所有connections指向同一个connect 引用);--->connections=1
--->org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#getSharedClient
--->构建客户端列表org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#buildReferenceCountExchangeClientList
--->构建一个客户端org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#buildReferenceCountExchangeClient
--->创建连接org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#initClient
--->client type setting str = netty [/Users/**/.m2/repository/org/apache/dubbo/dubbo/2.7.3/dubbo-2.7.3.jar!/META-INF/dubbo/internal/org.apache.dubbo.remoting.Transporter=[netty=org.apache.dubbo.remoting.transport.netty4.NettyTransporter]]
--->"codec" -> "dubbo"---->"heartbeat" -> "60000"---->client = Exchangers.connect(url, requestHandler);
--->org.apache.dubbo.remoting.exchange.Exchangers#connect(org.apache.dubbo.common.URL, org.apache.dubbo.remoting.exchange.ExchangeHandler)
--->org.apache.dubbo.remoting.exchange.Exchangers#getExchanger(java.lang.String) type = header
--->[/Users/**/.m2/repository/org/apache/dubbo/dubbo/2.7.3/dubbo-2.7.3.jar!/META-INF/dubbo/internal/org.apache.dubbo.remoting.exchange.Exchanger:header=org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger]
--->org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger#connect
---> new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);
--->构造 org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler#HeaderExchangeHandler
---> 构造 org.apache.dubbo.remoting.transport.DecodeHandler#DecodeHandler
--->org.apache.dubbo.remoting.Transporters#connect(org.apache.dubbo.common.URL, org.apache.dubbo.remoting.ChannelHandler...)
--->adaptiveExtension org.apache.dubbo.remoting.Transporters#getTransporter
--->org.apache.dubbo.common.extension.ExtensionLoader#getExtension(name=netty)
--->反射构造器创建:org.apache.dubbo.remoting.transport.netty4.NettyTransporter
--->org.apache.dubbo.remoting.transport.netty4.NettyTransporter#connect
--->org.apache.dubbo.remoting.transport.AbstractClient#AbstractClient
--->org.apache.dubbo.remoting.transport.netty4.NettyClient#doOpen 创建netty客户端(创建Bootstrap),并把处理逻辑 nettyClientHandler 接入
--->org.apache.dubbo.remoting.transport.AbstractClient#connect 建立netty链接
--->org.apache.dubbo.remoting.transport.netty4.NettyClient#doConnect
--->ChannelFuture future = bootstrap.connect(getConnectAddress());
--->持有链接 NettyClient.this.channel = newChannel------>Succeed connect to server.....
--->回到 遍历每一个provider url 循环!org.apache.dubbo.registry.integration.RegistryDirectory#toInvokers 继续下一个url链接创建 一个url对应一个新的key ;最终 Map<String, Invoker<T>> newUrlInvokerMap 如下
<<----org.apache.dubbo.registry.integration.RegistryDirectory#refreshInvoker 结束
<<----对于providers org.apache.dubbo.registry.integration.RegistryDirectory#refreshOverrideAndInvoker 结束
<<----依次执行 RegistryDirectory 注册目录 notify 方法 routers configurators providers 对应的URL 结束
<<----notify (org.apache.dubbo.registry.support.FailbackRegistry#notify)<<---doNotify (org.apache.dubbo.registry.support.FailbackRegistry#doNotify)<<-抽象通知框架<<-- org.apache.dubbo.registry.support.AbstractRegistry#notify 结束
<<----注册目录 执行订阅RegistryDirectory#subscribe 把 订阅URL 增加一个参数pair "category" :"providers,configurators,routers" 类别域
---> 继续 org.apache.dubbo.rpc.cluster.Cluster#join 合并 订阅目录 invokers 到一个虚拟 invoker(包含了所有的可用invokers集合)
--->Merge the directory invokers to a virtual invoker
--->SPI @SPI(FailoverCluster.NAME)
--->构造 org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker 调用失败重试其他客户端
<<----org.apache.dubbo.registry.integration.RegistryProtocol#doRefer
<<----org.apache.dubbo.registry.integration.RegistryProtocol#refer
<<----org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper#refer
<<----org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper#refer
<<----org.apache.dubbo.qos.protocol.QosProtocolWrapper#refer
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0)); ---->registry协议来注册消费者(consumer://),同时注册并获取服务提供者(dubbo://)---详细源码解析结束!!!
接下来分析:PROXY_FACTORY.getProxy(invoker); 源码:
代理工厂@SPI("javassist")org.apache.dubbo.rpc.ProxyFactory 默认使用javassist
--->创建org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory
--->完成transient volatile T ref代理对象的创建
--->org.apache.dubbo.config.ReferenceConfig#init 结束
--->org.apache.dubbo.config.ReferenceConfig#get 结束 ( 对应开始入口 org.apache.dubbo.config.ReferenceConfig#init 跟进 --->ref = createProxy(map); org.apache.dubbo.config.ReferenceConfig#get 方法初始化引用)
--->org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean 获取factoryBean结束----->spring框架继续启动
3 相关图片
3.1 过滤后可能只剩下符合条件的provider urls 比如只保留了stage环境的URL 3.2 抽象通知框架:org.apache.dubbo.registry.support.AbstractRegistry#notify 归类(keep every provider's category)
3.3 通过SPI确认 协议 dubbo是与否有class实现 org.apache.dubbo.common.extension.ExtensionLoader#hasExtension
3.4 遍历每一个provider url 循环!org.apache.dubbo.registry.integration.RegistryDirectory#toInvokers 最终 Map<String, Invoker<T>> newUrlInvokerMap 如下
3.5 遍历每一个provider url 循环!org.apache.dubbo.registry.integration.RegistryDirectory#toInvokers 最终 Map<String, Invoker<T>> newUrlInvokerMap key 示例
dubbo://172.16.208.142:20999/com.nini.wowo.service.RichService?anyhost=true&application=rec-experiment&bean.name=com.xiaodaka.adonis.service.RichService&check=false&cluster=failover&deprecated=false&dubbo=2.0.2&dynamic=true&executes=10&generic=false&group=STAGE&h5RichDualStreamNote.executes=5&interface=com.xiaodaka.adonis.service.RichService&lazy=false&loadbalance=random&methods=h5RichDualStreamNote,richByBatchNoteIds,richDualStreamNote&organization=xdk&owner=zw&pid=28616®ister=true®ister.ip=172.16.208.141&release=2.7.3&remote.application=adonis-provider&retries=1&revision=1.0.0&richByBatchNoteIds.executes=5&richDualStreamNote.executes=5&side=consumer&sticky=false&timeout=3000×tamp=1603522225128&version=1.0.0
最后
以上就是寂寞背包为你收集整理的【dubbo】dubbo 2.7+ 客户端引用过程—源码阅读的全部内容,希望文章能够帮你解决【dubbo】dubbo 2.7+ 客户端引用过程—源码阅读所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复