Dubbo 3.x源码(11)—Dubbo服务的发布与引用的入口

news2024/11/24 14:20:13

基于Dubbo 3.1,详细介绍了Dubbo服务的发布与引用的入口的源码。

此前我们学习了Dubbo配置的加载与覆盖的一系列源码:

  1. Dubbo 3.x源码(7)—Dubbo配置的加载入口源码
  2. Dubbo 3.x源码(8)—Dubbo配置中心的加载与优先级源码
  3. Dubbo 3.x源码(9)—Dubbo启动元数据中心源码
  4. Dubbo 3.x源码(10)—Dubbo初始化模块配置源码

在经过一系列的流程加载了Dubbo配置之后,接下来将会进行最重要的一步,也就是Dubbo服务的发布与引用的过程,该过程完毕之后,Dubbo可正式对外提供服务。那么Dubbo服务的发布与引用的入口在哪里呢?

1 Dubbo服务的发布与引用的入口

此前我们在Dubbo配置加载的部分学到过一个DubboBeanUtils#registerCommonBeans方法,此前在很多文章中提到的DubboBootstrapApplicationListener实际上在Dubbo3.1版本中是没有出现了,也就是说在最新的Dubbo源码中,基于spring的Dubbo的启动不再是通过DubboBootstrap类引导完成的,实际上是基于DubboDeployApplicationListener和DubboConfigApplicationListener这两个新加入的监听器来实现Dubbo启动的。

image.png

其中DubboDeployApplicationListener可以看作是DubboBootstrapApplicationListener的替代组件,而DubboConfigApplicationListener则用于加载Dubbo配置,DubboConfigApplicationListener的作用我们在Dubbo配置的加载部分已经讲了,现在我们来看看DubboDeployApplicationListener这个监听器的作用,它实际上就是最新版本的Dubbo服务的发布与引用的入口。

在spring容器启动的最后一个步也就是refresh方法内部最后的finishRefresh方法中,将会向所有监听器发布一个ContextRefreshedEvent事件,表示容器刷新完毕。

image.png
DubboDeployApplicationListener是一个ApplicationListener的实现,其可以监听ApplicationContextEvent事件,而ContextRefreshedEvent继承自ApplicationContextEvent,因此DubboDeployApplicationListener可以监听到该事件。

实际上,到这里就很明白了,DubboDeployApplicationListener#onApplicationEvent方法便是真正的Dubbo服务的发布与引用的入口。可以发现,实际上和原来的监听器DubboBootstrapApplicationListener的入口是一样的。

/**
 * DubboDeployApplicationListener的方法
 * <p>
 * 监听ApplicationContextEvent,启动或者关闭服务
 */
@Override
public void onApplicationEvent(ApplicationContextEvent event) {
    if (nullSafeEquals(applicationContext, event.getSource())) {
        if (event instanceof ContextRefreshedEvent) {
            //容器刷新完毕事件,启动服务
            onContextRefreshedEvent((ContextRefreshedEvent) event);
        } else if (event instanceof ContextClosedEvent) {
            //监听容器关闭事件,关闭服务
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }
}

private void onContextRefreshedEvent(ContextRefreshedEvent event) {
    //获取模块发布器
    ModuleDeployer deployer = moduleModel.getDeployer();
    Assert.notNull(deployer, "Module deployer is null");
    // start module
    //启动模块,启动服务
    Future future = deployer.start();

    // if the module does not start in background, await finish
    //如果模块没有在后台启动,则等待完成
    if (!deployer.isBackground()) {
        try {
            //调用get方法阻塞等待直到完成启动
            future.get();
        } catch (InterruptedException e) {
            logger.warn("Interrupted while waiting for dubbo module start: " + e.getMessage());
        } catch (Exception e) {
            logger.warn("An error occurred while waiting for dubbo module start: " + e.getMessage(), e);
        }
    }
}

2 start启动模块服务

最终是通过DefaultModuleDeployer#start方法启动服务的。

内部首先调用DefaultApplicationDeployer#initialize方法初始化应用程序发布器,之前学过该方法,只会初始化一次。随后调用startSync方法开始同步启动服务,这是本次学习的重点方法。

/**
 * DefaultModuleDeployer的方法
 * <p>
 * 启动模块服务
 */
@Override
public Future start() throws IllegalStateException {
    // initialize,maybe deadlock applicationDeployer lock & moduleDeployer lock
    //初始化应用程序发布器,之前学过该方法,只会初始化一次
    applicationDeployer.initialize();
    /*
     * 开始同步启动
     */
    return startSync();
}

3 startSync启动服务

该方法可以类比此前的DubboBootstrapApplicationListener中的start方法,内部将会先调用exportServices方法进行服务导出,随后调用referServices方法进行服务引用,如果看过此前版本的源码,那么这两个方法大家应该不会陌生吧。

/**
 * DefaultModuleDeployer的方法
 * <p>
 * 启动模块服务
 */
private synchronized Future startSync() throws IllegalStateException {
    //如果正在停止、已停止、已失败,那么抛出异常
    if (isStopping() || isStopped() || isFailed()) {
        throw new IllegalStateException(getIdentifier() + " is stopping or stopped, can not start again");
    }

    try {
        //如果正在启动或者启动完成,则直接返回
        if (isStarting() || isStarted()) {
            return startFuture;
        }
        //设置发布器的状态为STARTING,即正在发布
        onModuleStarting();

        //初始化模块模型,一般在此前的步骤中就初始化了
        initialize();

        // export services
        /*
         * 1 服务导出
         */
        exportServices();

        // prepare application instance
        // exclude internal module to avoid wait itself
        //先启动内部模块模型
        if (moduleModel != moduleModel.getApplicationModel().getInternalModule()) {
            applicationDeployer.prepareInternalModule();
        }

        // refer services
        /*
         * 2 服务引用
         */
        referServices();

        // if no async export/refer services, just set started
        //如果没有异步的导出/引用服务,只需设置已启动状态即可,默认情况
        if (asyncExportingFutures.isEmpty() && asyncReferringFutures.isEmpty()) {
            /*
             * 3 dubbo模块启动后的处理
             */
            onModuleStarted();
        } else {
            //异步的等待导出/引用服务完成
            frameworkExecutorRepository.getSharedExecutor().submit(() -> {
                try {
                    // wait for export finish
                    waitExportFinish();
                    // wait for refer finish
                    waitReferFinish();
                } catch (Throwable e) {
                    logger.warn("wait for export/refer services occurred an exception", e);
                } finally {
                    //异步回调完成,则设置已启动状态
                    onModuleStarted();
                }
            });
        }
    } catch (Throwable e) {
        onModuleFailed(getIdentifier() + " start failed: " + e, e);
        throw e;
    }
    return startFuture;
}

4 总结

本次我们主要学习Dubbo 3.x版本的Dubbo服务的发布与引用的入口,它和此前版的入口还是有些区别的,但是这不是重点,接下来的文章我们将会学习Dubbo3.x的exportServices方法服务导出,referServices方法服务引用的源码,这才是重点!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1029857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过 Helm Chart 部署 Easysearch

Easysearch 可以通过 Helm 快速部署了&#xff0c;快来看看吧&#xff01; Easysearch 的 Chart 仓库地址在这里 https://helm.infinilabs.com。 使用 Helm 部署 Easysearch 有两个前提条件&#xff1a; cert-managerlocal-path 我们先按照 Chart 仓库的说明来快速部署一下…

OpenCV之九宫格图像

将一张图像均等分成九份&#xff0c;然后将这九个小块按一定间隔&#xff08;九宫格效果&#xff09;拷贝到新画布上。效果如下图所示&#xff1a; 源码&#xff1a; #include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv;i…

基于矩阵分解算法的智能Steam游戏AI推荐系统——深度学习算法应用(含python、ipynb工程源码)+数据集(二)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 模型构建1&#xff09;定义模型结构2&#xff09;优化损失函数 3. 模型训练及保存1&#xff09;模型训练2&#xff09;模型保存 相关其它博客工程源代码下载其它资料下载 前言 本项目采用了矩阵分…

优维低代码实践:图片和搜索

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…

Unity中Shader模板测试使用到的二进制

文章目录 前言&#xff08;接上一篇文章&#xff09;一、模板测试公式1、简化版(在ReadMask默认值的情况下)2、完整版 二、二进制的值1、0 和 1组成2、符号3、二进制的与运算4、二进制和十进制转化 三、在Shader中的实际操作 前言&#xff08;接上一篇文章&#xff09; Unity中…

JimuReport积木报表 v1.6.2 版本正式发布—开源免费的低代码报表

项目介绍 一款免费的数据可视化报表&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于excel操作风格&#xff0c;通过拖拽完成报…

(Tekla Structures二次开发)获取当前模型文件夹路径

代码如下&#xff1a; TSM.Model model new TSM.Model();if(model.GetConnectionStatus()){ModelInfo modelInfo model.GetInfo();MessageBox.Show(modelInfo.ModelPath); // model.CommitChanges();}运行结果如下&#xff1a;

项目文章 | Plant Commun(IF:10.5)发表附属染色体调节植物-真菌互作从寄生到共生转换的分子作用机制

发表单位&#xff1a;中国林业科学院林木遗传育种国家重点实验室/中国林业科学研究院亚热带林业研究所 发表时间&#xff1a;2023年8月9日 期刊&#xff1a;Plant Communications&#xff08;IF&#xff1a;10.5&#xff09; 2023年8月9日&#xff0c;中国林业科学院林木遗传…

Postman应用——接口请求和响应(Get和Post请求)

文章目录 新增Request请求Get请求Post请求 Request请求响应Postman响应界面说明请求响应另存为示例&#xff08;模板&#xff09;Postman显示的响应数据清空请求响应数据保存到本地文件 这里只讲用的比较多的Get和Post请求方式&#xff0c;也可以遵循restful api接口规范&#…

Centos7部署gitlab

建议服务器配置不低于2C8G 1、安装必要的依赖 sudo yum install -y curl policycoreutils-python openssh-server perl2、配置极狐GitLab 软件源镜像 curl -fsSL https://packages.gitlab.cn/repository/raw/scripts/setup.sh | /bin/bash sudo yum install gitlab-jh -y3、…

Windows下SSH配置多账号

C:\Users\Administrator\.ssh 目录下新建config文件 config文件内容如下 配置了两个账号&#xff0c;举例如下 # github Host github.com HostName github.com IdentityFile ~/.ssh/github_id_rsa PreferredAuthentications publickey# gitee Host gitee.com HostName gitee.…

OR63 删除公共字符

目录 一、题目 二、代码 三、易错 一、题目 删除公共字符_牛客题霸_牛客网 二、代码 #include <iostream> #include <string> using namespace std;int main() {string s1,s2;getline(cin,s1);getline(cin,s2);string s3;int mark 0;//若s1中的字符在s2中不存…

线性调频雷达回波仿真+脉冲压缩仿真

雷达发射的线性调频信号&#xff1a; s ( t ) r e c t ( t τ ) e x p j 2 π f 0 t j π μ t 2 s(t)rect(\frac{t}{\tau})exp{j2\pi f_0tj\pi \mu t^2} s(t)rect(τt​)expj2πf0​tjπμt2 不考虑RCS&#xff0c;假设目标回波的幅度不变&#xff0c;那么目标反射回波可以…

Cpp/Qt-day050921Qt

目录 实现使用数据库的登录注册功能 头文件&#xff1a; registrwidget.h: widget.h: 源文件&#xff1a; registrwidget.c: widget.h: 效果图&#xff1a; 思维导图 实现使用数据库的登录注册功能 头文件&#xff1a; registrwidget.h: #ifndef REGISTRWIDGET_H #de…

爬虫 — 字体反爬

目录 一、安装字体软件 FontCreator二、百度智能云文字识别三、案例一四、案例二五、案例三六、安装 Tesseract1、安装步骤2、配置环境3、使用 Python 识别图片信息 七、案例四 一、安装字体软件 FontCreator 点击下载字体软件 FontCreator 安装包 1、同意协议&#xff0c;点击…

QT--day5

注册 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include<QPushButton> #include<QLineEdit> #include<QLabel> #include <QMessageBox> #include<QString> #include<QSqlDatabase> …

python教程:使用gevent实现高并发并限制最大并发数

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 import time import gevent from gevent.pool import Pool from gevent import monkey # 一&#xff0c;定义最大并发数 p Pool(20) # 二&#xff0c;导入gevent…

Python —— excel文件操作(超详细)

背景 很多公司还是用excel去管理测试用例的&#xff0c;所以为了减少重复繁琐的导出导出工作&#xff0c;学会如何用代码操作excel表格很实用~ 1、读取excel文件基本步骤 1、操作excel的一些库 1、xlrd&#xff1a;读取库&#xff0c;xlwt&#xff1a;写入&#xff0c;现在…

win10 Baichuan2-7B-Chat-4bits 上部署 百川2-7B-对话模型-4bits量化版

搞了两天才搞清楚跑通 好难呢,个人电脑 win10 ,6GB显存 个人感觉 生成速度很慢,数学能力不怎么行 没有ChatGLM2-6B 强,逻辑还行, 要求: 我的部署流程 1.下载模型 ,下载所有文件 然后 放到新建的model目录 https://huggingface.co/baichuan-inc/Baichuan2-7B-Chat-4bits/tr…

力扣刷题-数组-二分查找总结

前言 二分查找的使用前提/一般何时想到使用二分查找&#xff1a;数组为有序数组、数组中重复元素&#xff08;因为一旦有重复元素&#xff0c;使用二分查找法返回的元素下标可能不是唯一的&#xff09; 二分查找的关键 / 不容易写混乱的关键 / 谨记的不变量&#xff1a;区间定…