【dubbo】dubbo 2.7+ 客户端引用过程—源码阅读

17 篇文章 0 订阅

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&timestamp=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&register=true&register.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&timestamp=1603522225128&version=1.0.0

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自驱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值