Dubbo服务引入源码分析
简介
- 服务引入原理解析
- 路由链源码解析
- 服务静态目录与动态目录源码解析
- 服务引入源码解析
服务引入原理
当Spring启动过程中,会去给@Reference注解标注了的属性去进行赋值,赋值的对象为ReferenceBean中get()方法所返回的对象,这个对象是一个代理对象。
对于ReferenceBean,它表示应用想要引入的服务的信息,在执行get()时会做如下几步:
- 调用checkAndUpdateSubConfigs(),检查和更新参数,和服务提供者类似,把ReferenceBean里的属性的值更新为优先级最高的参数值
- 调用init()去生成代理对象ref,get()方法会返回这个ref
- 在生成代理对象ref之前,先把消费者所引入服务设置的参数添加到一个map中,等会根据这个map中的参数去从注册中心查找服务
- 把消费者配置的所有注册中心获取出来
a. 如果只有一个注册中心,那么直接调用Protocol的refer(interfaceClass, urls.get(0));得到一个Invoker对象
b. 如果有多个注册中心,则遍历每个注册中心,分别调用Protocol的refer(interfaceClass, url);得到一个Invoker对象添加到invokers中,然后把invokers调用CLUSTER.join(new StaticDirectory(u, invokers));封装所有invokers得到一个invoker, - 把最终得到的invoker对象调用PROXY_FACTORY.getProxy(invoker);得到一个代理对象,并返回,这个代理对象就是ref
- 总结:上文的Invoker对象,表示服务执行者,从注册中心refer下来的是一个服务执行者,合并invokers后得到的invoker也是一个服务执行者(抽象范围更大了)
接下来,来看Protorol.refer(interfaceClass, url)方法是怎么生成一个Invoker的
首先interfaceClass表示要引入的服务接口,url是注册中心的url(registry://),该url中有一个refer参数,参数值为当前所要引入服务的参数
调用doRefer(cluster, registry, type, url)
在doRefer方法中会生成一个RegistryDirectory
然后获取新版本中的路由器链,并添加到RegistryDirectory中去
RegistryDirectory监听几个目录(注意,完成监听器的订阅绑定后,会自动触发一次去获取这些目录上的当前数据)
a. 当前所引入的服务的动态配置目录:/dubbo/config/dubbo/org.apache.dubbo.demo.DemoService:1.1.1:g1.configurators
b. 当前所引入的服务的提供者目录:/dubbo/org.apache.dubbo.demo.DemoService/providers
c. 当前所引入的服务的老版本动态配置目录:/dubbo/org.apache.dubbo.demo.DemoService/configurators
d. 当前所引入的服务的老版本路由器目录:/dubbo/org.apache.dubbo.demo.DemoService/routers调用cluster.join(directory)得到一个invoker
返回invoker(如果消费者引入了多个group中的服务,那么这里返回的是new MergeableClusterInvoker
(directory);,否则返回的是new FailoverClusterInvoker (directory);) 但是,上面返回的两个Invoker都会被MockClusterInvoker包装,所以最终返回的是MockClusterInvoker。
获取服务提供者列表
Mock
路由 M–>N
负载均衡 N—>1
集群容错
构造NettyClient
发送数据
服务引入
- 构造Invoker
- DemoService 服务目录。当前服务的提供者列表 List
实际上是 List - 构造一个服务目录的时候要到注册中心查看
- 多少个提供者 List
就多少个 List - 监听 当前服务对应的节点
- 路由 TagRouter–>AppRouter–>ServiceRouter
本质上是构造一个代理对象。代理对象最重要的是Invoker
代理对象逻辑
1 | 代理对象.a() { |
- 代理对象
Invoker invoker 有这个就行了。 - Invoker
MockClusterInvoker.invoke()
FailoverClusterInvoker.invoke()
DubboInvoker.invoke()