上一次我们讲解了Dubbo的服务暴露, 这次我们来看一下Dubbo是如何调用服务的
本文会根据dubbo的架构图进行解析

目录
客户端启动流程
大家都知道,客户端在调用服务时只有接口没有相对应的实现类,所以呢,我们需要在调用服务时需要先生成一个代理,再通过代理去执行服务。

可以看到我们通过从ioc中获取DemoService的Bean,那其实本身客户端中并没有DemoService的bean,这个时候我们可以看到配置文件中进行了这样的一个配置使用了reference标签,在dubbo中reference标签配置的服务会被另一个Bean生成代理,那就是ReferenceBean,它会通过getObject()方法将生成的代理对象放入ioc中,所以点进去
<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>

这里会对接口的代理对象进行检查,如果没有则会初始化一个
public synchronized T get() {
checkAndUpdateSubConfigs();
if (destroyed) {
throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
}
// 检测 ref 是否为空,为空则通过 init 方法创建
if (ref == null) {
// init 方法主要用于处理配置,以及调用 createProxy 生成代理类
init();
}
return ref;
}
点进init()方法中,可以看到核心的方法就是创建代理对象的(能看到我们本身配置的一些信息,接口路径等等)

接着就是对提供者的数量的一个判断,是有多个还是单个,然后生成invoker,最后会根据invoker返回生成的代理,重点则在于如何生成invoker,这里的protocol是自适应的,所以会根据url中的信息选择对应的实现类,可以看到协议中使用的是registry,于是来到RegistryProtocol
// 单个注册中心或服务提供者(服务直连,下同)
if (urls.size() == 1) {
// 调用 RegistryProtocol 的 refer 构建 Invoker 实例
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0)); // registry://192.168.200.129:2181/org.apache.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.2&pid=14276&qos.port=33333&refer=application%3Ddemo-consumer%26check%3Dfalse%26dubbo%3D2.0.2%26interface%3Dorg.apache.dubbo.demo.DemoService%26lazy%3Dfalse%26methods%3DsayHello%26pid%3D14276%26qos.port%3D33333%26register.ip%3D192.168.200.10%26side%3Dconsumer%26sticky%3Dfalse%26timestamp%3D1622603489641®istry=zookeeper×tamp=1622603494381
} else {
// 多个注册中心或多个服务提供者,或者两者混合
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
// 获取所有的 Invoker 到 invokers中
for (URL url : urls) {
// 通过 ref_protocol 调用 refer 构建 Invoker,refprotocol 会在运行时
// 根据 url 协议头加载指定的 Protocol 实例,并调用实例的 refer 方法
invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // use last registry url
}
}
if (registryURL != null) { // registry url is available
// use RegistryAwareCluster only when register's CLUSTER is available
// 如果注册中心链接不为空,则将使用 AvailableCluster
URL u = registryURL.addParameter(CLUSTER_KEY, RegistryAwareCluster.NAME);
// The invoker wrap relation would be: RegistryAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, will execute route) -> Invoker
// 创建 StaticDirectory 实例,并由 Cluster 对多个 Invoker 进行合并 Cluster扩展点默认找的是FailoverCluster
invoker = CLUSTER.join(new StaticDirectory(u, invokers));
} else { // not a registry url, must be direct invoke.
invoker = CLUSTER.join(new StaticDirectory(invokers));
}
}
// invoker 可用性检查
if (shouldCheck() && !invoker.isAvailable()) {
throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
}
if (logger.isInfoEnabled()) {
logger.info("
Dubbo服务调用详解:客户端代理生成与服务发现流程

最低0.47元/天 解锁文章
6655

被折叠的 条评论
为什么被折叠?



