概要
服务端启动过程
-
Step 1:生成注册中心Registry URL集合
对dubbo的registries属性进行校验(<dubbo:registry标签或properties文件中读取dubbo.registry.address属性),并获取注册中心的地址,生成Registry URL集合
-
Step 2:根据配置参数构造URL(如dubbo版本号、端口号等等)
-
Step 3:服务暴露
-
本地服务暴露过程
- 构造 injvm URL
- 默认Javassist动态代理根据接口、代理和URL生成AbstractProxyInvoker匿名实例
- InjvmProtocol通过export方法构造出InjvmExporter
- 将InjvmExporter对象存入ServiceConfig对象的exporters属性中,本地服务暴露完成
-
远程服务暴露过程
-
获取monitor标签的监控地址信息,并作为monitor参数放入服务提供者的URL中
-
将服务提供者的URL地址作为export参数的值放入注册地址URL中
-
默认Javassist动态代理根据接口、代理和注册地址URL生成AbstractProxyInvoker匿名实例
-
RegistryProtocol通过export方法重新构造出Exporter对象,过程如下:
-
将上一步创建的Invoker封装成RegistryProtocol静态内部类InvokerDelegete
-
调用DubboProtocol的export方法,并返回DubboExporter
- 构造DubboExporter
- 开启ExchangeServer服务
-
根据DubboExporter等信息重新构造出ExporterChangeableWrapper
-
获取注册中心,并注册服务
-
获取订阅URL,构建订阅回调notify,并向注册中心订阅URL,同时注册回调监听器
-
重新构造Exporter对象
-
-
将RegistryProtocol通过export方法构造出的Exporter对象存入ServiceConfig对象的exporters属性中,服务暴露完成
-
-
消费端启动过程
-
Step 1:获取配置参数放到map中
-
Step 2:引用服务
-
引用本地服务
- 构造InjvmInvoker
- ProtocolListenerWrapper中封装成ListenerInvokerWrapper对象返回,在ListenerInvokerWrapper内部遍历所有监听器并执行其refered方法
- 在ProtocolFilterWrapper类中对返回的Invoker对象构建filter链
-
引用远程服务(调用RegistryProtocol的refer方法引用远程服务)
-
获取注册中心(若已经创建则直接返回,否则创建)
- 启动文件保存定时器(如生成dubbo-registry-127.0.0.1.cache)
- loadProperties()把上⾯面创建的缓存⽂文件读进内存中
- 获取该注册中⼼的所有的订阅者,并通知到每个订阅者下的所有监听者(listener)
- FailbackRegistry再开启一个线程来启动失败重试定时器,retryPeriod默认值是5s
-
获取分组(group)信息
-
构造consumer订阅URL,并注册到注册中心上,同时通知每个订阅者下的所有监听者(listener)
-
创建RegistryDirectory,并作为Listener放到订阅该consumer URL的Listener集合中并发送订阅请求
-
获取服务端提供者providers URL列表,并根据invokerURL列表转换为invoker列表,最后将invokers列表转成与方法的映射关系(缓存到RegistryDirectory中methodInvokerMap属性中)
转换规则如下:
- 如果url已经被转换为invoker,则不在重新引用,直接从缓存中获取,注意如果url中任何一个参数变更也会重新引用
- 如果传入的invoker列表不为空,则表示最新的invoker列表
- 如果传入的invokerUrl列表是空,则表示只是下发的override规则或route规则,需要重新交叉对比,决定是否需要重新引用
-
根据RegistryDirectory生成MockClusterInvoker并返回
-
-
-
Step 3:创建代理
调用JavassistProxyFactory的getProxy方法来创建代理,并放ReferenceConfig类接口代理类引用ref中(默认使用Javassist代理)
消费端调用过程
-
Step 1:cluster层调用
调用MockClusterInvoker的invoke方法,最终调用AbstractClusterInvoker的invoke方法,调用过程如下:
-
检查RPC Cluster invoker中要执行的接口是否被销毁,若销毁,则抛出异常
-
在调用提供者之前,会获取当前线程临时变量里的RpcContext对象,再将RpcContext对象里的参数设置到Invocation对象
-
列出所有的Invoker,即从RegistryDirectory中的methodInvokerMap属性中取出所有的Invoker
在消费端启动过程中已经方法和对应的invoker关系存放到了RegistryDirectory中的methodInvokerMap属性中
-
获取方法上配置的负载均衡策略,若没有配置,选择默认的策略
-
进入到Step 2进行protocol层调用
-
-
Step 2:protocol层调用
Protocol层作用:封装RPC调用,以Invocation和Result为中心,扩展接口为Protocol、Invoker和Exporter。Protocol是服务域,它是Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理。Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
以下是protocol层的调用次序
- ConsumerContextFilter的invoke 方法
- FutureFilter的invoke方法
- MonitorFilter中的invoke方法
- DubboInvoker中invoke方法(最终会调用到目标方法)