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

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()

在这里插入图片描述
初始化服务的一些元信息,然后调用doExport()

ServiceConfig.doExport()

在这里插入图片描述
判断是否该服务已经暴露过,如果暴露过了则不再进行暴露,若没有则会调用doExportUrls()。

ServiceConfig.doExportUrls()

在这里插入图片描述
首先获得服务注册器,当前的服务注册器中的内容如下:
在这里插入图片描述
仅有两个dubbo自带的两种服务,一个是心跳服务EchoService,另一个是GenericService,提供泛化接口,用来进行泛化调用。这两个服务这里暂时不做说明,本文的重点不在这里。

执行完第二行代码后,服务注册器当中多了我们想要暴露的服务UserService,服务中有服务的描述,记录了服务的名字、服务的接口类型,服务的方法等信息。
在这里插入图片描述
第三行代码是往服务注册器当中注册服务提供者,执行之后repository如下,提供者记录了服务的实例、元数据、服务配置信息等。
在这里插入图片描述
之后获取用于注册的url,此例子中只有一个zookeeper注册中心。
在这里插入图片描述
for循环,遍历protocols协议,这里也说明了dubbo支持多协议,可以将一个服务暴露不同协议的服务。

调用doExportUrlsFor1Protocol(protocolConfig, registryURLs)

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

该方法的逻辑很长,暂时不用去深究细节,仅仅关注服务暴露的部分。
在这里插入图片描述
获取该url中配置的scope,根据这个参数有两种暴露可以选择,一种是本地暴露,另一个是远程暴露

本地暴露
在这里插入图片描述
在这里插入图片描述
构建一个InjvmExporter,不需要开启netty服务,相当提供一个在本地可调用服务。

远程暴露
在这里插入图片描述
基于代理工厂将接口的实现类ref封装成Invoker对象,然后调用Protocol的export方法,经过一系列的包装类,调用RegistryProtocol中的export方法。

RegistryProtocol.export(final Invoker< T > originInvoker)

在这里插入图片描述
doLocalExport真正执行开启服务并暴露服务的方法。最终会调用到DubboProtocol中的export。

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

DubboProtocol.export(Invoker< T > invoker)

在这里插入图片描述
基于url获取服务的key,也就是服务的全限定类名:端口号

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

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

DubboProtocol.openServer(URL url)

在这里插入图片描述
serverMap当中还没有当前的协议服务ProtocolServer,所以会调用createServer来构建一个协议服务。

DubboProtocol.createServer(URL url)

在这里插入图片描述
协议url中设置一些参数,比如心跳服务的周期,默认1分钟等。

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

调用Exchangers.bind 构建协议服务。
在这里插入图片描述
参数校验,然后获取Exchanger调用bind
在这里插入图片描述
调用Transporters.bind
在这里插入图片描述
获取Transporter,然后调用bind方法

NettyTransporter.bind(URL url, ChannelHandler handler)

最终来到NettyTransporter当中的bind
在这里插入图片描述
基于url和ChannelHandler开启netty服务。
在这里插入图片描述
调用父类的构造方法
在这里插入图片描述
属性的设置,然后调用doOpen,实现真正开启netty服务的方法。

NettyServer.doOpen()

在这里插入图片描述
学过netty的应该比较熟悉这段代码,初始化并开启了一个netty服务,服务就这样暴露出去了。
构建好的服务会保存在DubboProtocol的serverMap当中
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/gongsenlin341/article/details/115219035