1. 前言
在 Dubbo 框架中,服务消费者通过 XML 配置方式引用服务时,涉及多个模块之间的协作。
不放dubbo官方的设计图了,这里同样放一张自己画的服务消费者调用图,后面的介绍也是围绕这张图来的。
以下是服务消费者引用服务时,各个模块之间的源码方法调用关系的详细说明。
2. 简述过程
在 dubbo-config-spring
项目模块中,dubbo 框架定义了 dubbo.xsd
。业务使用时,可以基于 定义好的标签(<dubbo:reference>
等),在 xml 中配置要发布的服务。
这部分内容可以查看前面写的 《Spring XML自定义命名空间》。
服务提供者在启动时,DubboNamespaceHandler
中会根据 XML 配置中的 <dubbo:reference>
标签引用服务,整个过程大致如下:
解析 XML 配置:
- 解析
<dubbo:reference>
标签,创建ReferenceConfig
对象。
- 解析
服务引用:
- 调用
ReferenceConfig.get()
方法,开始服务引用过程。
- 调用
协议引用:
ReferenceConfig.get()
方法内部调用Protocol.refer()
方法,通过具体的协议实现服务的引用。
服务发现和负载均衡:
- 通过
Registry
和Directory
进行服务发现,并通过Cluster
和LoadBalance
实现负载均衡。
- 通过
代理创建:
- 使用
ProxyFactory
创建服务接口的代理对象。
- 使用
3. ReferenceConfig 模块
- 作用:负责服务引用的配置和管理,是服务引用的入口。
- 关键方法:
ReferenceConfig.get()
public class ReferenceConfig<T> {
private volatile T ref;
public synchronized T get() {
if (ref == null) {
init();
}
return ref;
}
private void init() {
// 调用 Protocol.refer()
Invoker<?> invoker = protocol.refer(interfaceClass, url);
// 创建代理对象
ref = proxyFactory.getProxy(invoker);
}
}
4. Protocol 模块
- 作用:负责服务的导出和引用。
- 关键方法:
Protocol.refer()
public interface Protocol {
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}
5. RegistryProtocol.refer()
- 作用:处理服务发现和引用相关的逻辑。
调用关系:
- 获取注册中心:通过
RegistryFactory
获取Registry
实例。 - 创建服务目录:创建
RegistryDirectory
,用于管理服务提供者的地址列表。 - 订阅服务:通过
Registry
订阅服务提供者信息。 - 集群合并:通过
Cluster.join()
将多个服务提供者的Invoker
合并为一个集群Invoker
。
- 获取注册中心:通过
public class RegistryProtocol implements Protocol {
@Override
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
// 1. 获取注册中心
Registry registry = registryFactory.getRegistry(url);
// 2. 创建服务目录
RegistryDirectory<T> directory = new RegistryDirectory<>(type, url);
// 3. 订阅服务提供者
directory.setRegistry(registry);
directory.subscribe(subscribeUrl);
// 4. 返回集群 Invoker
return cluster.join(directory);
}
}
6. Cluster 模块
- 作用:负责将多个服务提供者的
Invoker
合并为一个集群Invoker
,实现负载均衡和容错。 - 关键方法:
Cluster.join()
public interface Cluster {
<T> Invoker<T> join(Directory<T> directory) throws RpcException;
}
7. Invoker 模块
- 作用:表示一个可调用的服务引用,是服务调用的核心模型。
- 关键方法:
Invoker.invoke()
用于执行远程调用。
public interface Invoker<T> {
Result invoke(Invocation invocation) throws RpcException;
}
8. ProxyFactory 模块
- 作用:负责创建服务接口的代理对象。
- 关键方法:
ProxyFactory.getProxy()
public interface ProxyFactory {
<T> T getProxy(Invoker<T> invoker) throws RpcException;
}
9. LoadBalance 模块
- 作用:提供负载均衡策略,选择合适的
Invoker
进行调用。 - 关键方法:
LoadBalance.select()
public interface LoadBalance {
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
}
10. 总结
在 Dubbo 服务消费者的引用过程中,多个模块协同工作:
- ReferenceConfig:负责服务引用的配置和入口。
- Protocol 和 Invoker:负责服务的引用和调用。
- Registry 和 Directory:负责服务的发现和动态管理。
- Cluster 和 LoadBalance:负责负载均衡和容错。
- ProxyFactory:负责创建服务接口的代理对象。
图示化流程
ReferenceConfig.get()
└── RegistryProtocol.refer()
└── Registry.getRegistry()
└── RegistryDirectory.subscribe()
└── Cluster.join()
└── LoadBalance.select()
└── ProxyFactory.getProxy()
ReferenceConfig.get():
- 解析服务引用配置,准备服务引用。
- 调用
Protocol.refer()
进行服务引用。
RegistryProtocol.refer():
- 获取注册中心并创建服务目录。
- 订阅服务提供者信息。
- 通过
Cluster.join()
返回集群 Invoker。
Cluster.join():
- 合并多个服务提供者的
Invoker
,实现负载均衡。
- 合并多个服务提供者的
ProxyFactory.getProxy():
- 创建服务接口的代理对象,供消费者使用。
LoadBalance.select():
- 在服务调用时,选择合适的
Invoker
进行调用。
- 在服务调用时,选择合适的
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。