Dubbo3 源码解读-宋小生-8:Dubbo启动器DubboBootstrap借助双重校验锁的单例模式进行对象的初始化

简介: > Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双十一基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。> 本文是
Dubbo3 已经全面取代 HSF2 成为阿里的下一代服务框架,2022 双十一基于 Dubbo3 首次实现了关键业务不停推、不降级的全面用户体验提升,从技术上,大幅提高研发与运维效率的同时地址推送等关键资源利用率提升超 40%,基于三位一体的开源中间件体系打造了阿里在云上的单元化最佳实践和统一标准,同时将规模化实践经验与技术创新贡献开源社区,极大的推动了开源技术与标准的发展。

本文是 Dubbo 社区贡献者宋小生基于 Dubbo3 3.0.8 版本撰写的源码解析博客,在 Dubbo3 开源&内部技术栈统一的情况下,期望能对集团内的开发者了解 Dubbo3 背后的实现原理有所帮助。可点此查看 博客原文

本篇是宋小生系列 8/30 篇。同时,由 Dubbo3 团队领导的源码解读系列也正在进行中,感兴趣的同学可加入钉钉群了解详情: 28165003194

8.1 启动器简介

在说启动器之前先把视野拉回第一章《1-从一个服务提供者的Demo说起》我们的Demo代码,下面只贴一下核心代码:

public class Application {
    public static void main(String[] args) throws Exception {
            startWithBootstrap();
    }
    private static void startWithBootstrap() {
        //前面的文章都在说这个服务配置对象的创建,中间又说了分层域模型,扩展加载机制
        ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
        //为服务配置下服务接口和服务实现,下面两行用来初始化对象就不详细说了
        service.setInterface(DemoService.class);
        service.setRef(new DemoServiceImpl());
        //这一个篇章主要说这里:
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))
            .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
            .protocol(new ProtocolConfig(CommonConstants.DUBBO, -1))
            .service(service)
            .start()
            .await();
    }
}

Dubbo3 往云原生的方向走自然要针对云原生应用的应用启动,应用运行,应用发布等信息做一些建模,这个DubboBootstrap就是用来启动Dubbo服务的.类似于Netty的Bootstrap类型和ServerBootstrap启动器

8.2 双重校验锁的单例模式创建启动器对象的

Dubbo的bootstrap类为啥要用单例模式:

通过调用静态方法getInstance()获取单例实例。之所以设计为单例,是因为Dubbo中的一些类(如ExtensionLoader)只为每个进程设计一个实例。

下面就来直接看代码吧,代码胜千言:
对象的调用代码如下:

DubboBootstrap bootstrap = DubboBootstrap.getInstance();   

DubboBootstrap获取对象的getInstance()方法:

 public static DubboBootstrap getInstance() {
         //双重校验锁第一次判断空
        if (instance == null) {
            //为空都进行排队
            synchronized (DubboBootstrap.class) {
            //双重校验锁第二次判断空 上面为空的都排队了这里得判断下
                if (instance == null) {
                    //调用重载方法获取对象
                    instance = DubboBootstrap.getInstance(ApplicationModel.defaultModel());
                }
            }
        }
        return instance;
    }

DubboBootstrap获取对象重载的getInstance(ApplicationModel applicationModel)方法:

computeIfAbsent() 方法对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hashMap 中。

instanceMap设计为Map<ApplicationModel, DubboBootstrap>类型 Key,意味着可以为多个应用程序模型创建不同的启动器,启动多个服务

 public static DubboBootstrap getInstance(ApplicationModel applicationModel) {
        return instanceMap.computeIfAbsent(applicationModel, _k -> new DubboBootstrap(applicationModel));
    }

8.3 DubboBootstrap的构造器代码

构造器代码是逻辑比较复杂的地方,我们先来看下代码

private DubboBootstrap(ApplicationModel applicationModel) {
        //存储应用程序启动模型
        this.applicationModel = applicationModel;
        //获取配置管理器ConfigManager:  配置管理器的扩展类型ApplicationExt ,扩展名字config
        configManager = applicationModel.getApplicationConfigManager();
        //获取环境信息Environment: 环境信息的扩展类型为ApplicationExt,扩展名字为environment
        environment = applicationModel.getModelEnvironment();
        //执行器存储仓库(线程池)ExecutorRepository: 扩展类型为ExecutorRepository,默认扩展扩展名字为default
        executorRepository = applicationModel.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
        //初始化并启动应用程序实例ApplicationDeployer,DefaultApplicationDeployer类型
        applicationDeployer = applicationModel.getDeployer();
        // listen deploy events
        //为发布器 设置生命周期回调
        applicationDeployer.addDeployListener(new DeployListenerAdapter<ApplicationModel>() {
            @Override
            public void onStarted(ApplicationModel scopeModel) {
                notifyStarted(applicationModel);
            }

            @Override
            public void onStopped(ApplicationModel scopeModel) {
                notifyStopped(applicationModel);
            }

            @Override
            public void onFailure(ApplicationModel scopeModel, Throwable cause) {
                notifyStopped(applicationModel);
            }
        });
        //将启动器对象注册到应用程序模型applicationModel的Bean工厂中
        // register DubboBootstrap bean
        applicationModel.getBeanFactory().registerBean(this);
    }
目录
相关文章
|
3月前
|
Dubbo Cloud Native 网络协议
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
69 1
|
3月前
|
缓存 Dubbo Java
Dubbo 第三节_ Dubbo的可扩展机制SPI源码解析
Dubbo会对DubboProtocol对象进⾏依赖注⼊(也就是⾃动给属性赋值,属性的类型为⼀个接⼝,记为A接⼝),这个时候,对于Dubbo来说它并不知道该给这个属性赋什么值,换句话说,Dubbo并不知道在进⾏依赖注⼊时该找⼀个什么的的扩展点对象给这个属性,这时就会预先赋值⼀个A接⼝的⾃适应扩展点实例,也就是A接⼝的⼀个代理对象。在调⽤getExtension去获取⼀个扩展点实例后,会对实例进⾏缓存,下次再获取同样名字的扩展点实例时就会从缓存中拿了。Protocol是⼀个接。但是,不是只要在⽅法上加了。
|
3月前
|
XML Dubbo Java
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)(二)
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)
55 2
|
3月前
|
XML Cloud Native Dubbo
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(一)
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南
214 1
|
3月前
|
Dubbo Cloud Native 应用服务中间件
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
【Dubbo3 终极特性】「云原生三中心架构」带你探索 Dubbo3 体系下的配置中心和元数据中心、注册中心的原理及开发实战(中)
107 1
|
3月前
|
Cloud Native Dubbo 应用服务中间件
【Dubbo3技术专题】拥有新时代的通信协议,引领云原生迈向更高的舞台 | 解密Dubbo3是如何从微服务升华到云原生领域
【Dubbo3技术专题】拥有新时代的通信协议,引领云原生迈向更高的舞台 | 解密Dubbo3是如何从微服务升华到云原生领域
90 1
|
3月前
|
XML 监控 Dubbo
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)(一)
【Dubbo3技术专题】回顾Dubbo2.x的技术原理和功能实现及源码分析(温故而知新)
95 1
|
3月前
|
XML Dubbo Java
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南(二)
【Dubbo3高级特性】「提升系统安全性」手把手教你如何通过令牌进行Dubbo3服务验证及服务鉴权控制实战指南
237 0
|
3月前
|
Kubernetes Dubbo 应用服务中间件
【Dubbo3终极特性】「流量治理体系」一文教你如何搭建Dubbo3的控制台服务Dubbo-Admin
【Dubbo3终极特性】「流量治理体系」一文教你如何搭建Dubbo3的控制台服务Dubbo-Admin
235 0
|
3月前
|
Dubbo Java 应用服务中间件
微服务框架(十七)Dubbo协议及编码过程源码解析
  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为Dubbo协议、线程模型、和其基于Netty的NIO异步通讯机制及源码