天天看点

Dubbo服务暴露原理解析,带你手撕源码

文章目录

      • 1.概述
      • 2.服务暴露源码分析
        • ServiceConfig.export()
        • ServiceConfig.doExport()
        • ServiceConfig.doExportUrls()
        • ServiceConfig.doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List< URL > registryURLs)
        • RegistryProtocol.export(final Invoker< T > originInvoker)
        • DubboProtocol.export(Invoker< T > invoker)
        • DubboProtocol.openServer(URL url)
        • DubboProtocol.createServer(URL url)
        • NettyTransporter.bind(URL url, ChannelHandler handler)
        • NettyServer.doOpen()

1.概述

本文将一步一步的分析Dubbo服务暴露过程的源码,探究其实现的过程,选择的Dubbo版本是2.7.8。

测试代码如下:

@Test
public void openService() throws IOException {
    // 服务配置
    ServiceConfig serviceConfig = new ServiceConfig();
    // 应用
    ApplicationConfig app = new ApplicationConfig("coderead-server");
    serviceConfig.setApplication(app);
    // 协议
    ProtocolConfig protocol = new ProtocolConfig("dubbo");
    protocol.setPort(8080);
    serviceConfig.setProtocol(protocol);
    // 注册中心
    RegistryConfig registry = new RegistryConfig("zookeeper://127.0.0.1:2181");
    serviceConfig.setRegistry(registry);
    // 接口
    serviceConfig.setInterface(UserService.class);
    // 实现
    serviceConfig.setRef(new UserServiceImpl(8080));
    // 开启服务
    serviceConfig.export();
    System.in.read();
}
           

测试代码前面的部分就是设置服务的一些配置信息

服务的暴露是通过serviceConfig.export()来完成的,下面将分析export的执行过程,看看它究竟做了哪些事情。

2.服务暴露源码分析

ServiceConfig.export()

Dubbo服务暴露原理解析,带你手撕源码

初始化服务的一些元信息,然后调用doExport()

ServiceConfig.doExport()

Dubbo服务暴露原理解析,带你手撕源码

判断是否该服务已经暴露过,如果暴露过了则不再进行暴露,若没有则会调用doExportUrls()。

ServiceConfig.doExportUrls()

Dubbo服务暴露原理解析,带你手撕源码

首先获得服务注册器,当前的服务注册器中的内容如下:

Dubbo服务暴露原理解析,带你手撕源码

仅有两个dubbo自带的两种服务,一个是心跳服务EchoService,另一个是GenericService,提供泛化接口,用来进行泛化调用。这两个服务这里暂时不做说明,本文的重点不在这里。

执行完第二行代码后,服务注册器当中多了我们想要暴露的服务UserService,服务中有服务的描述,记录了服务的名字、服务的接口类型,服务的方法等信息。

Dubbo服务暴露原理解析,带你手撕源码

第三行代码是往服务注册器当中注册服务提供者,执行之后repository如下,提供者记录了服务的实例、元数据、服务配置信息等。

Dubbo服务暴露原理解析,带你手撕源码

之后获取用于注册的url,此例子中只有一个zookeeper注册中心。

Dubbo服务暴露原理解析,带你手撕源码

for循环,遍历protocols协议,这里也说明了dubbo支持多协议,可以将一个服务暴露不同协议的服务。

调用doExportUrlsFor1Protocol(protocolConfig, registryURLs)

ServiceConfig.doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List< URL > registryURLs)

该方法的逻辑很长,暂时不用去深究细节,仅仅关注服务暴露的部分。

Dubbo服务暴露原理解析,带你手撕源码

获取该url中配置的scope,根据这个参数有两种暴露可以选择,一种是本地暴露,另一个是远程暴露

本地暴露

Dubbo服务暴露原理解析,带你手撕源码
Dubbo服务暴露原理解析,带你手撕源码

构建一个InjvmExporter,不需要开启netty服务,相当提供一个在本地可调用服务。

远程暴露

Dubbo服务暴露原理解析,带你手撕源码

基于代理工厂将接口的实现类ref封装成Invoker对象,然后调用Protocol的export方法,经过一系列的包装类,调用RegistryProtocol中的export方法。

RegistryProtocol.export(final Invoker< T > originInvoker)

Dubbo服务暴露原理解析,带你手撕源码

doLocalExport真正执行开启服务并暴露服务的方法。最终会调用到DubboProtocol中的export。

RegistryProtocol 此处的作用就是等服务开启暴露完毕后,将服务的地址注册到注册中心当中。此例子中就是将服务的地址注册到zookeeper。

DubboProtocol.export(Invoker< T > invoker)

Dubbo服务暴露原理解析,带你手撕源码

基于url获取服务的key,也就是服务的全限定类名:端口号

将Invoker封装成DubboExporter,保存在exporterMap当中。

然后调用openServer(url)开启服务。

DubboProtocol.openServer(URL url)

Dubbo服务暴露原理解析,带你手撕源码

serverMap当中还没有当前的协议服务ProtocolServer,所以会调用createServer来构建一个协议服务。

DubboProtocol.createServer(URL url)

Dubbo服务暴露原理解析,带你手撕源码

协议url中设置一些参数,比如心跳服务的周期,默认1分钟等。

获取远程路由服务,默认使用netty

调用Exchangers.bind 构建协议服务。

Dubbo服务暴露原理解析,带你手撕源码

参数校验,然后获取Exchanger调用bind

Dubbo服务暴露原理解析,带你手撕源码

调用Transporters.bind

Dubbo服务暴露原理解析,带你手撕源码

获取Transporter,然后调用bind方法

NettyTransporter.bind(URL url, ChannelHandler handler)

最终来到NettyTransporter当中的bind

Dubbo服务暴露原理解析,带你手撕源码

基于url和ChannelHandler开启netty服务。

Dubbo服务暴露原理解析,带你手撕源码

调用父类的构造方法

Dubbo服务暴露原理解析,带你手撕源码

属性的设置,然后调用doOpen,实现真正开启netty服务的方法。

NettyServer.doOpen()

Dubbo服务暴露原理解析,带你手撕源码

学过netty的应该比较熟悉这段代码,初始化并开启了一个netty服务,服务就这样暴露出去了。

构建好的服务会保存在DubboProtocol的serverMap当中

Dubbo服务暴露原理解析,带你手撕源码