Dubbo中的统一契约是如何实现的?

在dubbo-common模块中,有一个URL类专门用于封装URL,如下所示。

在这里插入图片描述

在URL类中,我们来看一个核心构造函数,如下所示。

public URL(String protocol,

String username,

String password,

String host,

int port,

String path,

Map<String, String> parameters,

Map<String, Map<String, String>> methodParameters) {

if (StringUtils.isEmpty(username)

&& StringUtils.isNotEmpty(password)) {

throw new IllegalArgumentException(“Invalid url, password without username!”);

}

this.protocol = protocol;

this.username = username;

this.password = password;

this.host = host;

this.port = Math.max(port, 0);

this.address = getAddress(this.host, this.port);

// trim the beginning “/”

while (path != null && path.startsWith(“/”)) {

path = path.substring(1);

}

this.path = path;

if (parameters == null) {

parameters = new HashMap<>();

} else {

parameters = new HashMap<>(parameters);

}

this.parameters = Collections.unmodifiableMap(parameters);

this.methodParameters = Collections.unmodifiableMap(methodParameters);

}

可以看到,Dubbo对于URL的核心封装,基本与互联网中的URL封装是一致的。

在Dubbo的dubbo-common模块提供了处理URL的工具类:URLBuilder和URLStrParser。如下所示。

在这里插入图片描述

这两个类的实现还是比较简单的,小伙伴们可以自行阅读Dubbo的源码。

接下来,我们一起来看看在Dubbo内部,URL是如何实现统一契约的?

[](()Dubbo中URL的实际应用


这里,我们主要通过三方面来简单聊聊URL在Dubbo内部的实际应用:

  • URL在SPI中的应用。

  • URL在服务注册中的应用。

  • URL在服务发现中的应用。

[](()URL在SPI中的应用

稍微了解过Dubbo的小伙伴都知道,Dubbo具有高度的可扩展性,而这种扩展性是基于Dubbo自身的SPI来实现的。在Dubbo实现的SPI中,URL又起到了非常重要的作用。

在Dubbo SPI的实现中,一个典型的场景就是被@Adaptive注解修饰的接口方法,例如,在dubbo-registry-api 模块中的RegistryFactory接口中的getRegistry()方法上被@Adaptive({“protocol”})注解修饰。如下所示。

在这里插入图片描述

说明RegistryFactory接口中的getRegistry()方法是一个适配器方法,Dubbo在运行的过程中,会为getRegistry()方法动态生成RegistryFactory$Adaptive类型。例如,生成的RegistryFactory$Adaptive类型如下所示。

public class RegistryFactory$Adaptive

implements RegistryFactory {

public Registry getRegistry(org.apache.dubbo.common.URL arg0) {

if (arg0 == null) throw new IllegalArgumentException(“”);

org.apache.dubbo.common.URL url = arg0;

String extName = (url.getProtocol() == null ? “dubbo” : url.getProtocol());

if (extName == null)

throw new IllegalStateException(“”);

RegistryFactory extension = (RegistryFactory) ExtensionLoader.getExtensionLoader(RegistryFactory.class).getExtension(extName);

return extension.getRegistry(arg0);

}

}

这段代码相对来说还是比较容易理解的,生成的RegistryFactory$Adaptive会自动实现getRegistry()方法,在getRegistry()方法中,会获取URL中的protocol参数来确定URL的协议,如果获取的protocol为空,则使用默认的dubbo协议,有了这个协议,就能够通过SPI动态加载具体的扩展实现类。

我们在Dubbo的dubbo-registry-api模块中找到RegistryProtocol类,如下所示。

在这里插入图片描述

找到其中的getRegistry()方法并打上断点,如下所示。

在这里插入图片描述

接下来,debug启动Dubbo的Provider示例,如下所示。

在这里插入图片描述

可以看到,此时使用的protocol协议为zookeeper。有关Dubbo中SPI的实现,我们后面再详细剖析,今天,小伙伴们有个大致的了解即可。

[](() 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 URL在服务注册中的应用

在Dubbo中的服务注册实现中,URL同样起到了非常重要的作用。这里,我使用的注册中心是Zookeeper,所以,我们在dubbo-registry-zookeeper模块中找到ZookeeperRegistry类,如下所示。

在这里插入图片描述

找到其中的doRegister()方法,打上断点,如下所示。

在这里插入图片描述

debug启动Dubbo自带的provider示例,如下所示。

在这里插入图片描述

可以看到,在注册到Zookeeper中的URL中,包含了protocol协议、host主机名、port端口号、path请求路径,parameters参数等信息。

[](()URL在服务发现中的应用

Dubbo中服务的消费者Consumer在启动时,会向Zookeeper注册中心订阅自身需要调用的服务,那具体是如何通过URL订阅的呢?我们同样在dubbo-registry-zookeeper模块中的ZookeeperRegistry类中找到doSubscribe()方法。在doSubscribe()方法中打上断点,如下所示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值