入口是ReferenceBean#afterPropertiesSet
Step1:如果consumer为空,说明dubbo:reference标签未设置consumer属性,如果一个dubbo:consumer标签,则取该实例,如果存在多个dubbo:consumer 配置,则consumer必须设置,否则会抛出异常:“Duplicate consumer configs”。
Step2:如果application为空,则尝试从BeanFactory中查询dubbo:application实例,如果存在多个dubbo:application配置,则抛出异常:“Duplicate application configs”。
Step3:如果ServiceBean的module为空,则尝试从BeanFactory中查询dubbo:module实例,如果存在多个dubbo:module,则抛出异常:"Duplicate module configs: "。
Step4:尝试从BeanFactory中加载所有的注册中心,注意ServiceBean的List< RegistryConfig> registries属性,为注册中心集合。
Step5:尝试从BeanFacotry中加载一个监控中心,填充ServiceBean的MonitorConfig monitor属性,如果存在多个dubbo:monitor配置,则抛出"Duplicate monitor configs: "。
Step6:判断是否初始化,如果为初始化,则调用getObject()方法,该方法也是FactoryBean定义的方法,ReferenceBean是dubbo:reference所真实引用的类(interface)的实例工程,getObject发返回的是interface的实例,而不是ReferenceBean实例。
处理dubbo服务消费端resolve机制,也就是说消息消费者只连服务提供者,绕过注册中心。
Step7:构建Map,封装服务消费者引用服务提供者URL的属性,这里主要填充side:consume(消费端)、dubbo:2.0.0(版本)、timestamp、pid:进程ID。
8. Dubbo的method和argument标签的属性也填到attributeMap中
9.调用ReferenceConfig#createProxy,来创建对应的消费proxy
10.协议为injvm就是本地协议。scope为remote,则为远程协议,则isJvmRefer设置为false
11.对于普通的consumer,就从注册中心订阅服务
12.如果只有一个服务提供者URL,就直接根据协议构建invoker
13.如果有多个服务提供者,就构成了一个集群
14.从消费者URL获取interfaces的值,分隔出单个服务应用接口
15.根据需要实现的接口,使用jdk或Javassist创建代理类
我们来分享远程引用服务。在 Dubbo 中提供多种协议( Protocol ) 的实现,大体流程一致,本文以 Dubbo Protocol 为例子,这也是 Dubbo 的默认协议。
dubbo://
Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。
特性
缺省协议,使用基于 mina 1.1.7
和 hessian 3.2.1
的 tbremoting 交互。
- 连接个数:单连接
- 连接方式:长连接
- 传输协议:TCP
- 传输方式:NIO 异步传输
- 序列化:Hessian 二进制序列化
- 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
- 适用场景:常规远程服务方法调用
相比本地引用,远程引用会多做如下几件事情:
- 向注册中心订阅,从而发现服务提供者列表。
- 启动通信客户端,通过它进行远程调用。
- 正常流程,一般为远程引用。
url
配置项,定义直连地址,可以是服务提供者的地址(直连调用服务端),也可以是注册中心的地址
多 urls
时,循环调用 Protocol#refer(type, url)
方法,引用服务,返回 Invoker 对象。此时,会有多个 Invoker 对象,需要进行合并。因为会有多个注册中心,所以会有多个url
获得真实的注册中心的 URL
获得注册中心 Registry 对象
获得服务引用配置参数集合
调用 #doRefer(cluster, registry, type, url)
方法,执行服务引用
获得服务引用配置集合 parameters
。注意,url
传入 RegistryDirectory 后,经过处理并重新创建,所以 url != directory.url
,所以获得的是服务引用配置集合
创建订阅 URL 对象
调用 RegistryService#register(url)
方法,向注册中心注册自己
调用 Directory#subscribe(url)
方法,向注册中心订阅服务提供者 + 路由规则 + 配置规则。
创建 Invoker 对象。向本地注册表,注册消费者。
返回 Invoker 对象。
- 设置编解码器为
"Dubbo"
协议,即 DubboCountCodec 。 - 第 16 行:默认开启心跳功能。
- 第 19 至 31 行:连接服务器,创建客户端
装饰器模式
基于装饰器模式,所以,每个实现方法,都是调用 client
的对应的方法