0
点赞
收藏
分享

微信扫一扫

[Dubbo3.0.8源码解析系列]-16-模块发布器发布服务全过程



目录

  • ​​16-模块发布器发布服务全过程​​
  • ​​16.1 简介​​
  • ​​16.2 导出服务的入口​​
  • ​​16.3 服务配置导出服务​​

16-模块发布器发布服务全过程

16.1 简介

Dubbo做为服务治理框架,比较核心的就是服务相关的概念,这里我先贴个找到的关于Dubbo工作原理的架构图:

[Dubbo3.0.8源码解析系列]-16-模块发布器发布服务全过程_分布式

如果按完整服务启动与订阅的顺序我们可以归结为以下6点:

  • 导出服务(提供者)
  • 服务提供方通过指定端口对外暴露服务
  • 注册服务(提供者)
  • 提供方向注册中心注册自己的信息
  • (服务发现)-订阅服务(消费者)
  • 服务调用方通过注册中心订阅自己感兴趣的服务
  • (服务发现)-服务推送(消费者)
  • 注册中心向调用方推送地址列表
  • 调用服务(消费者调用提供者)
  • 调用方选择一个地址发起RPC调用
  • 监控服务
  • 服务提供方和调用方的统计数据由监控模块收集展示

上面的完整的服务启动订阅与调用流程不仅仅适用于Dubbo 同样也适用于其他服务治理与发现的模型, 一般服务发现与服务调用的思路就是这样的,我们将以上内容扩展,暴漏服务可以使用http,tcp,udp等各种协议,注册服务可以注册到Redis,Dns,Etcd,Zookeeper等注册中心中,订阅服务可以主动去注册中心查询服务列表,服务发现可以让注册中心将服务数据动态推送给消费者.Dubbo其实就是基于这种简单的服务模型来扩展出各种功能的支持,来满足服务治理的各种场景,了解了这里可能各位同学就想着自行开发一个简单的微服务框架了。

回到主题,从以上的服务完整发布调用流程可以看到,所有的功能都是由导出服务(提供者)开始的,只有提供者先提供了服务才可以有真正的服务让消费者调用。

之前的博客内容 链接:​​<<12-全局视野来看Dubbo3.0.8的服务启动生命周期>>​​ 我们了解了 DefaultModuleDeployer模块器启动的流程,其中在start代码的模版方法中开始了导出服务的功能,这里我们来详细看下服务发布的全过程:

入口代码: DefaultModuleDeployer的发布服务方法

private void exportServices() {
//从配置管缓存中查询缓存的所有的服务配置然后逐个服务发布
for (ServiceConfigBase sc : configManager.getServices()) {
exportServiceInternal(sc);
}
}

16.2 导出服务的入口

入口代码: DefaultModuleDeployer的发布服务方法

private void exportServices() {
//从配置管缓存中查询缓存的所有的服务配置然后逐个服务发布
for (ServiceConfigBase sc : configManager.getServices()) {
exportServiceInternal(sc);
}
}

主要流程为遍历初始化的服务配置列表然后逐个服务开始到处

内部导出服务代码:

exportServiceInternal方法:

private void exportServiceInternal(ServiceConfigBase sc) {

ServiceConfig<?> serviceConfig = (ServiceConfig<?>) sc;
//服务配置刷新 配置优先级覆盖
if (!serviceConfig.isRefreshed()) {
serviceConfig.refresh();
}
//服务已经导出过了就直接返回
if (sc.isExported()) {
return;
}
//是否异步方式导出 全局配置或者服务级其中一个配置了异步则异步处理
if (exportAsync || sc.shouldExportAsync()) {
//异步其实就是使用线程来导出服务serviceExportExecutor
ExecutorService executor = executorRepository.getServiceExportExecutor();
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
if (!sc.isExported()) {
sc.export();
exportedServices.add(sc);
}
} catch (Throwable t) {
logger.error(getIdentifier() + " export async catch error : " + t.getMessage(), t);
}
}, executor);

asyncExportingFutures.add(future);
} else {
//同步导出服务
if (!sc.isExported()) {
sc.export();
exportedServices.add(sc);
}
}
}

这个逻辑里面做了一些基本的操作,可以直接看注释然后调用ServiceConfig的export的来导出服务,继续往后看服务配置的导出服务方法。

16.3 服务配置导出服务

核心的服务导出代码是在服务配置中来做的ServiceConfig的 export() 方法

ServiceConfig的 export() 方法代码如下:

@Override
public void export() {
//已经导出过服务直接放那会
if (this.exported) {
return;
}

// ensure start module, compatible with old api usage
//确保模块启动了(基本的初始化操作执行了)
getScopeModel().getDeployer().start();
//悲观锁
synchronized (this) {
//双重校验
if (this.exported) {
return;
}
//配置是否刷新 前面初始化时候已经刷新过配置
if (!this.isRefreshed()) {
this.refresh();
}
//服务导出配置配置为false则不导出
if (this.shouldExport()) {
this.init();

if (shouldDelay()) {
doDelayExport();
} else {
doExport();
}
}
}
}



举报

相关推荐

0 条评论