Dubbo的服务引用流程主要包括配置初始化、代理创建、注册中心订阅及网络连接四个核心阶段,具体流程如下:
一、入口触发与配置初始化
- 触发入口
通过ReferenceConfig.get()
方法触发服务引用流程,该方法内部调用init()
进行配置校验(如接口名、协议合法性等)。 - 配置组装
加载注册中心地址(如ZK/Nacos),将服务接口、协议、超时参数等封装为URL格式的Map,为后续代理创建提供元数据。
二、动态代理创建与调用链封装
- 生成Invoker调用链
- 通过
Protocol.refer()
(如RegistryProtocol
)根据URL选择具体协议(Dubbo/HTTP)。 - 构建责任链式Invoker:依次添加监控、重试、超时等Filter(如
TimeoutFilter
),形成多层装饰的调用链。
- 通过
- 动态代理生成
- 由
ProxyFactory
(默认使用Javassist)创建服务接口的代理对象,屏蔽远程调用细节,使消费者可本地化调用。 - 代理逻辑:拦截方法调用,将参数封装为RPC请求,通过Invoker调用链转发。
- 由
三、注册中心订阅与服务发现
- 订阅服务变更
- 向注册中心(如ZK)发起订阅,监听
providers
节点(服务提供者列表)、configurators
节点(路由规则)的变化。 - 注册中心实时推送提供者地址的增删事件。
- 向注册中心(如ZK)发起订阅,监听
- 刷新服务列表
- 通过
RegistryDirectory
接收变更通知,动态更新本地可用服务列表。 - 新服务提供者加入时,自动创建Netty长连接并封装为
DubboInvoker
。
- 通过
四、网络连接与客户端初始化
- 建立通信连接
- 根据提供者地址列表,通过
Exchangers.connect()
创建Netty客户端(默认单连接,可配置多连接)。
- 根据提供者地址列表,通过
- 负载均衡与集群容错
- 调用时通过集群模块(
Cluster
)选择具体Invoker,结合策略(如随机RandomLoadBalance
)路由到目标服务。 - 失败时按容错策略(如
FailoverCluster
自动重试)处理。
- 调用时通过集群模块(
五、引用时机与优化
- 懒汉式 vs 饿汉式
- 懒汉式(默认):服务首次被注入或调用时触发引用,减少启动开销。
- 饿汉式:配置
init=true
时,Spring容器初始化阶段通过afterPropertiesSet()
提前引用。
- 本地引用优化
若消费者与提供者在同一JVM,直接走本地调用,避免网络传输。
流程总结
graph LR
A[ReferenceConfig.get()] --> B[配置校验与URL组装]
B --> C[Protocol.refer生成Invoker链]
C --> D[注册中心订阅服务变更]
D --> E[创建Netty客户端连接]
E --> F[ProxyFactory生成代理对象]
F --> G[调用时负载均衡与容错]
关键设计点:
- 代理模式 + 责任链实现透明化远程调用;
- 观察者模式监听注册中心动态更新服务列表;
- 策略模式支持灵活的路由与容错机制。