1 从spring BeanDefinitionParser 解析开始 (给自己一小时一撸到底)
2 源码部分
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106BeanDefinitionParser --> 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 示例
复制代码
1dubbo://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内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复