乐趣区

关于分布式:Dubbo中的统一契约是如何实现的

写在后面

之前,很多小伙伴私信我:如何能力疾速的把握 Dubbo 的外围原理和源码。所以,我写了一篇《我是如何在短期内疾速把握 Dubbo 的原理和源码的(纯干货)?》。对于 Dubbo 的源码解析系列文章,我也在思考如何让源码解析的文章变得更加简略易懂,所以,我调整了写 Dubbo 源码解析文章的策略,力求让小伙伴们可能以更简略、易懂的形式彻底把握 Dubbo 源码。明天,咱们先说说 Dubbo 中的对立契约是如何实现的。

文章已收录到:

https://github.com/sunshinelyz/technology-binghe

https://gitee.com/binghe001/technology-binghe

不得不说的 URL

URL 全称为对立资源定位符,它可能在互联网中定位到惟一的一个网络地址。URL 的格局如下所示。

protocol://username:password@host:port/path?key=value&key=value

其中,各个局部的简要阐明如下所示。

  • protocol:URL 的协定。最常见的协定就是 HTTP 和 HTTPS,其余的还有 FTP、WS、FILE、SMTP 等。
  • username:用户名。
  • password:明码。
  • host:主机,通常是域名或者 IP 地址。
  • port:主机的端口号。
  • path:申请的指标文件的门路。
  • parameters:申请的具体参数信息,这里为 key=value&key=value。

这就是咱们互联网中的 URL 的简略阐明。

那么,在 Dubbo 外部,大量的办法接管的参数都是以 URL 进行封装的,那么,URL 在 Dubbo 外部到底起到了什么作用呢?咱们持续往下看。

Dubbo 中的 URL

总的来说,在 Dubbo 外部,服务提供者 Provider 会将本身的相干信息封装成 URL 注册到 Zookeeper 或其余注册核心中,从而对外裸露本人提供的服务。而服务消费者 Consumer 也会通过 URL 的模式向 Zookeeper 或其余注册核心订阅本人想要调用的服务。而在 Dubbo 的 SPI 实现中,URL 又会参加扩大实现的逻辑解决。所以说,URL 在 Dubbo 的实现中是十分重要的。也能够这么说,Dubbo 中的 URL 就是 Dubbo 的对立契约。

咱们先来看一下 Dubbo 中的 URL 具体长什么样吧,通过调试 Dubbo 自带 Provider 的示例源码,咱们能够看到在 Dubbo 中的 URL 如下所示。

dubbo://192.168.175.1:20880/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-annotation-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=15012&release=&side=provider&timestamp=1610857629484

这也是 Provider 注册到 Zookeeper 或者其余注册核心的信息。各个局部的阐明如下所示。

  • dubbo:应用的是 dubbo 协定。
  • host:主机的 IP 地址为 192.168.175.1。
  • port:端口号为 20880。
  • path:这里的申请门路为:org.apache.dubbo.demo.DemoService
  • parameters:申请的参数信息,这里为:anyhost=true&application=dubbo-demo-annotation-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=15012&release=&side=provider&timestamp=1610857629484。

既然 Dubbo 是向 Zookeeper 或其余注册核心注册这些信息的,那 Dubbo 外部是如何对 URL 进行封装的呢。

在 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 的实现,咱们前面再具体分析,明天,小伙伴们有个大抵的理解即可。

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()办法中打上断点,如下所示。

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

咱们能够看到,Dubbo 的 Consumer 会向 Zookeeper 传入如下参数进行服务的订阅操作。

consumer://192.168.175.1/org.apache.dubbo.demo.DemoService?application=dubbo-demo-annotation-consumer&category=providers,configurators,routers&dubbo=2.0.2&init=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=15184&side=consumer&sticky=false&timestamp=1610860963037

其中的 protocol 为 consumer,示意订阅协定。category 示意要订阅的分类,这里是 providers,configurators,routers 三个分类。interface 示意要订阅的接口服务,这里是 org.apache.dubbo.demo.DemoService。methods 示意要订阅的办法,这里是 sayHello,sayHelloAsync。

还有一点须要留神的是:在服务注册的过程中,Dubbo 会将 URL 转化为 Zookeeper 门路将信息注册到 Zookeeper 中;在服务发现的过程中,Dubbo 会将 URL 转化为 Zookeeper 门路,从而监听 Zookeeper 目录的变动来订阅相干的服务。

总之,在 Dubbo 外部通过 URL 实现了对立的契约。你学会了吗?

举荐浏览

  • 冰河开始对 Dubbo 下手了!
  • 鸟瞰 Dubbo 全局,浏览源码前必须把握这些!!
  • 我是如何在短期内疾速把握 Dubbo 的原理和源码的(纯干货)?

好了,明天就到这儿吧,我是冰河,大家有啥问题能够在下方留言,一起交换技术,一起进阶,一起牛逼~~

退出移动版