dubbo3.0引用源码详尽
2023-11-14 16:15:22 0 举报
dubbo3.0引用源码详尽
作者其他创作
大纲/内容
这就是当前接口根据应用级服务发现找到的ClusterInvoker,有4层,MockClusterInvoker ---invoker属性---------- >ClusterFilterInvoker----filterInvoker------->ClusterCallbackRegistrationInvoker----originalInvoker属性------>FailoverClusterInvoker-------directory属性------->ServiceDiscoveryRegistryDirectory-----invokers属性-------->newInvokers-------->DubboInvoker/TripleInvoker
List<Invoker<T>> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values()));//将这些invoker放入到org.apache.dubbo.rpc.cluster.directory.AbstractDirectory#invokers属性中,this也就是//ServiceDiscoveryRegistryDirectory对象this.setInvokers(multiGroup ? new BitList<>(toMergeInvokerList(newInvokers)) : new BitList<>(newInvokers));
得到应用级别的ClusterInvoker
refreshInvoker(instanceUrls);
for (int i = 0; i < connectNum; i++) { clients.add(buildReferenceCountExchangeClient(url)); }return clients;
2
下面的这些信息,不就是2.7版本的,注册到注册中心的内容吗
org.apache.dubbo.springboot.demo.DemoService2:dubbo
把nacosEventListener绑定到Nacos中,即通过namingService,绑定到DefaultPublisher对象中
//进一步判断,根据消费者url匹配出符合的服务端url放入到categoryListlistener.notify(categoryList);
connections=0
DynamicDirectory<T> font color=\"#5b79e8\
//这里就是区别于接口级服务的引用了org.apache.dubbo.registry.client.ServiceDiscoveryRegistry#doSubscribe
去看2.7的处理方式
去看3.0的处理方式
return (ClusterInvoker<T>) cluster.join(font color=\"#5b79e8\
当服务端的信息发生变化的时候,即:dataId为\"providers:org.apache.dubbo.springboot.demo.DemoService::\
赋值给MigrationInvoker对象的invoker属性
只走应用级别发现
去生成Netty客户端
//在这里构造过滤器链,注意是按照降序排列的 if (!CollectionUtils.isEmpty(filters)) { for (int i = filters.size() - 1; i >= 0; i--) { final ClusterFilter filter = filters.get(i); final Invoker<T> next = last; //构建过滤器链中的节点,一个节点对应一个filter对象 last = new CopyOfClusterFilterChainNode<>(font color=\"#ed77b6\
typedClients = buildReferenceCountExchangeClientList(font color=\"#e9d66f\
org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener#notifyAddressChanged
如果两者都有具体的Invoker,那则取出具体的Invoker数量
new ClusterFilterInvoker(clusterInvoker)根据dubbo自己的spi去构建拦截器链reference.filter consumer
然后放到这个serviceUrls属性里面
font color=\"#5b79e8\
//这里就是区别于应用级的引用了org.apache.dubbo.registry.nacos.NacosRegistry#doSubscribe
org.apache.dubbo.config.ReferenceConfig#init
应用级和接口级服务发现都会走,但最终也只会二选一
//serviceInstancesChangedListener是个ServiceInstancesChangedListener//url是消费端端元数据即:consumer://ip:port.........//listener是上面的ServiceDiscoveryRegistryDirectory对象,这里把listener//放入到了serviceInstancesChangedListener对象中font color=\"#e74f4c\
服务URLdubbo://实例ip:port/org.apache.dubbo.springboot.demo.DemoService
[ { \"app\": \"dubbo-springboot-demo-provider\
refreshServiceDiscoveryInvoker()
//在Transporters.connect方法里面去创建netty客户端 return new HeaderExchangeClient(Transporters.connect(font color=\"#e9d66f\
启动Netty客户端
return new MockClusterInvoker<T>(font color=\"#5b79e8\
FORCE_APPLICATION
ClusterInvoker
serviceDiscovery.addServiceInstancesChangedListener(serviceInstancesChangedListener);
得到接口级别的ClusterInvoker
tmpInvoker = builder.buildClusterInvokerChain(font color=\"#ed77b6\
1.直接根据接口信息,去注册中心获取接口级别的元数据,注意,是注册中心不是配置中心
TripleInvoker
当服务端的信息发生变化的时候,即:dataId为\"dubbo-springboot-demo-provider\
getClients(url)
DubboInvoker
serviceInstances的值就是它里面的内容,具体如下
connections0
font color=\"#ec7270\
//serviceName的值为\"providers:org.apache.dubbo.springboot.demo.DemoService::\"List<Instance> font color=\"#ec7270\
根据这些url对象,去生成对应协议的的Invoker对象
注意,这个时候又是从nacos的注册中心里面去获取应用的元数据了
org.apache.dubbo.config.ReferenceConfig#get得到一个dubbo服务端的接口的代理对象
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#initClient
从配置中心获取接口级别的元数据
refreshOverrideAndInvoker(instanceUrls);
1.去生成DubboInvoker
//metadataReport是配置中心对象metadataInfo = MetadataUtils.getMetadata(font color=\"#569230\
字如其名,迁移Invoker,这是用于3.0和2.7版本的兼容
赋值给MigrationInvoker对象的serviceDiscoveryInvoker属性
ExchangeClient exchangeClient = initClient(font color=\"#e9d66f\
font color=\"#a23c73\
doOnEvent(event);
refreshOverrideAndInvoker(providerURLs);
由于每个实例的元数据有自己的版本号,即\"dubbo.metadata.revision\",所以继续处理成key为版本号,valule为ServiceInstance的数据结构,revisionToInstances
遍历revisionToInstances,即根据版本去找各自的元数据
org.apache.dubbo.registry.integration.RegistryProtocol#referorg.apache.dubbo.registry.integration.RegistryProtocol#doRefer
refreshInterfaceInvoker()
接口2:tri
决定到底用谁calcPreferredInvoker(newRule);
MigrationStep step
listener.notify(urls);
org.apache.dubbo.registry.client.migration.DefaultMigrationAddressComparator#shouldMigrate
1
先去元数据中心,根据接口名称找到有哪些项目提供了这个接口的具体服务,也就是服务端,的应用名这里的元数据中心可以是nacos的配置中心或者是zk上的节点directory.subscribe(toSubscribeUrl(urlToRegistry));
int connections = font color=\"#e0c431\
2.对服务端的接口级元数据的监听
开始
生成独立的客户端
遍历serviceInstances因为同一应用会有多个实例,但是他们的名字相同,即:集群,如图中所示在这里遍历同名实例
先看这里
dubbo.metadata.storage-type的值为remote,即接口级服务的的元数据在nacos的配置中心中
如果为空
把instances处理成URL对象
ExchangeClient[] clients = new ExchangeClient[connections]; for (int i = 0; i < clients.length; i++) { clients[i] = initClient(url); } return clients;
migrateToForceInterfaceInvoker()
//font color=\"#5b79e8\
如果clients不为空,则直接返回clients
2.对服务端的应用级元数据的监听
refreshInvoker(urls);
服务URLdubbo://实例ip:port/org.apache.dubbo.springboot.demo.DemoService2
//key是\"192.168.3.28:20881\"String key = url.getAddress();//从缓存中根据服务提供者的ip:port去获取以有的客户端Object clients = referenceClientMap.get(key);
org.apache.dubbo.config.ReferenceConfig
org.apache.dubbo.springboot.demo.DemoService:dubbo
//同接口级的引用一样调用到该方法去创建ClusterInvoker对象//org.apache.dubbo.registry.integration.RegistryProtocol#doCreateInvokerreturn doCreateInvoker(font color=\"#5b79e8\
DubboInvoker的生成过程
serviceInstancesChangedListener.onEvent(new ServiceInstancesChangedEvent(font color=\"#ec7270\
//根据SHARE_CONNECTIONS_KEY重新获取connectionsList<ReferenceCountExchangeClient> shareClients=getSharedClient(font color=\"#e0c431\
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol#buildReferenceCountExchangeClientList
dubbo.metadata.storage-type的值为local,即接口级服务的的元数据在服务提供者的本地
List<URL> font color=\"#e9d66f\
调用到org.apache.dubbo.registry.client.ServiceDiscoveryRegistryDirectory.notify方法
把serviceInstancesChangedListener包装成NacosEventListener对象
最终把确定出来的ClusterInvoker赋值给赋值给MigrationInvoker对象的currentAvailableInvoker属性
赋值给MigrationInvoker对象的serviceDiscoveryInvoker和currentAvailableInvoker属性
DubboInvoker<T> invoker = new DubboInvoker<T>(font color=\"#a66a30\
migrateToApplicationFirstInvoker()
migrateToForceApplicationInvoker()
服务URLdubbo://实例2ip:port/org.apache.dubbo.springboot.demo.DemoService
//protocol是DubboProtocol对象//type的值是org.apache.dubbo.springboot.demo.DemoServicereturn font color=\"#4ccbcd\
font color=\"#4ccbcd\
由于serviceUrls里面放到是所有接口级服务的信息,所有在这个里面要根据消费端端url对象来筛选出适合当前接口的服务端接口级信息,并放入到urls
//url是服务端元数据,即:consumer://ip:port.......//listener是NacosAggregateListener对象,它里面包装了font color=\"#5b79e8\
接口1:tri
采用共享客户端的方式
把RegistryChildListenerImpl绑定到Nacos中,即通过namingService,绑定到DefaultPublisher对象中
生成一个MigrationInvoker对象
//serviceName的值是\"dubbo-springboot-demo-provider\"this.namingService.subscribe(font color=\"#ec7270\
基于MigrationInvoker生成代理对象
这里创建的是应用级导出专用的ServiceDiscoveryRegistryDirectory
如果二者只有其中一个有具体的值,那就没得选,就用这一个
AbstractClusterInvoker<T> last = buildInterceptorInvoker(new ClusterFilterInvoker<>(clusterInvoker));
服务URLtri://实例ip:port/接口1
服务URLdubbo://实例1ip:port/org.apache.dubbo.springboot.demo.DemoService
List<Invoker<T>> newInvokers = Collections.unmodifiableList(new ArrayList<>(newUrlInvokerMap.values()));//将这些invoker放入到org.apache.dubbo.rpc.cluster.directory.AbstractDirectory#invokers属性中,this也就是RegistryDirectory对象this.setInvokers(multiGroup ? new BitList<>(toMergeInvokerList(newInvokers)) : new BitList<>(newInvokers));
return protocolBindingRefer(font color=\"#a66a30\
return (ClusterInvoker<T>) cluster.join(directoryfont color=\"#323232\
((float) newAddressSize / (float) oldAddressSize) >= threshold为true则是应用级ClusterInvoker,否则用接口级ClusterInvokerthreshold默认为0,表示优先用应用级ClusterInvoker如果threshold配置为1,则可以认为应用级具体的Invoker数大于或等于接口级具体的Invoker数,则采用应用级ClusterInvoker,否则用接口级ClusterInvoker,threshold越大就越倾向于应用级的ClusterInvoker
APPLICATION_FIRST默认
org.apache.dubbo.registry.integration.RegistryDirectory#notify
org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener#serviceUrls
这里是接口级别专用的RegistryDirectory对象
//同应用级的引用一样调用到该方法去创建ClusterInvoker对象//org.apache.dubbo.registry.integration.RegistryProtocol#doCreateInvokerreturn doCreateInvoker(font color=\"#5b79e8\
下面把serviceInstancesChangedListener注册到serviceDiscovery对象中
2.根据subscribedServices里面的应用名去配置中心获取应用的元数据
getClients(url)的返回值放入在DubboInvoker的clients属性中
这里去构建消费端端拦截器链
1.先获取接口 - 应用映射关系,也就是mapping类型的配置
//doJoin(directory)返回的是return new FailoverClusterInvoker<>(directory);return buildClusterInterceptors(doJoin(directory));
把NacosAggregateListener包装成RegistryChildListenerImpl对象
org.apache.dubbo.remoting.transport.netty4.NettyClient#initBootstrap
只走接口级别发现
metadataInfo = proxyHolder.getProxy().getMetadataInfo(ServiceInstanceMetadataUtils.getExportedServicesRevision(instance));
这就是当前接口根据应用级服务发现找到的ClusterInvoker,有4层,MockClusterInvoker ---invoker属性---------- >ClusterFilterInvoker----filterInvoker------->ClusterCallbackRegistrationInvoker----originalInvoker属性------>FailoverClusterInvoker-------directory属性------->RegistryDirectory-----invokers属性-------->newInvokers------->DubboInvoker
进一步判断,根据消费者url匹配出符合的服务端url
proxyHolder = MetadataUtils.referProxy(instance);去构造MetadataService这个消费者,去和服务端的MetadataService服务区通信,那么怎么知道这个服务的端口号和其他数据的呢? 就是在\"metadata\"节点里面
//url是消费者元数据,即consumer://ip:port........//listener是上面的font color=\"#5b79e8\
//servcieName就是\"“dubbo-springboot-demo-provider”\"//serviceDiscovery是NacosServiceDiscovery对象List<ServiceInstance> serviceInstances = serviceDiscovery.getInstances(serviceName);
FORCE_INTERFACE
[ { \"ip\": \"192.168.3.28\
调用服务端的本地服务区获取接口级别服务的元数据
服务URLtri://实例ip:port/接口2
Exchangers.connect(font color=\"#e9d66f\
return last
return getTransporter(url).connect(font color=\"#e9d66f\
0 条评论
回复 删除
下一页