当前位置: 首页 > news >正文

Dubbo之DubboBootstrap源码解析

功能描述

  • DubboBootstrap是Dubbo的启动类,包含服务启动、初始化、预处理配置、销毁清理等核心功能

功能分析

核心DubboBootstrap类分析

主要成员变量分析

private static volatile DubboBootstrap instance; //缓存者启动类的实例对象,以static形式存储,便于其它类调用private final AtomicBoolean awaited = new AtomicBoolean(false); //是否等待private final Lock lock = new ReentrantLock();private final Condition condition = lock.newCondition();private final Lock destroyLock = new ReentrantLock(); //销毁清理时用到的锁private final ExecutorService executorService = newSingleThreadExecutor();private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); //事件派发器private final ExecutorRepository executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); //线程池仓库private final ConfigManager configManager; //配置管理器private final Environment environment;private ReferenceConfigCache cache; //引用配置的缓存对象private volatile boolean exportAsync; //是否异步暴露private volatile boolean referAsync; //是否异步引用private AtomicBoolean initialized = new AtomicBoolean(false); //初始化标识private AtomicBoolean started = new AtomicBoolean(false); //启动标识private AtomicBoolean ready = new AtomicBoolean(true); //是否已经准备好环境private AtomicBoolean destroyed = new AtomicBoolean(false);private volatile ServiceInstance serviceInstance; //服务实例private volatile MetadataService metadataService; //元数据服务private volatile Set<MetadataServiceExporter> metadataServiceExporters;private List<ServiceConfigBase<?>> exportedServices = new ArrayList<>(); //已经暴露的服务列表private List<Future<?>> asyncExportingFutures = new ArrayList<>(); //异步暴露时使用的Future列表

主要成员方法分析

获取DubboBootstrap的实例对象

public static DubboBootstrap getInstance() { //获取实例(使用单例模式)if (instance == null) {synchronized (DubboBootstrap.class) {if (instance == null) { //synchronized + 双重检查,线程安全且缩小锁的范围instance = new DubboBootstrap();}}}return instance;
}

私有的构造函数

private DubboBootstrap() { //私有的构造函数configManager = ApplicationModel.getConfigManager(); //config对象的本地配置environment = ApplicationModel.getEnvironment();     //获取环境信息DubboShutdownHook.getDubboShutdownHook().register();ShutdownHookCallbacks.INSTANCE.addCallback(new ShutdownHookCallback() { //注册钩子函数,当容器停止时,对DubboBootstrap进行销毁处理@Overridepublic void callback() throws Throwable {DubboBootstrap.this.destroy();}});
}

做初始化

public void initialize() { //初始化if (!initialized.compareAndSet(false, true)) {return; //此处initialized为true时进入,表明是已经初始化过来,就不在初始化}ApplicationModel.initFrameworkExts(); //初始化框架配置startConfigCenter(); //启动配置中心(拉取远程的配置写到本地缓存中)loadRemoteConfigs(); //加载远程配置(包含RegistryConfig、ProtocolConfig)、并写到ConfigManager对应的缓存中checkGlobalConfigs(); //检查Config是否正确startMetadataCenter(); //启动元数据中心initMetadataService(); //创建MetadataService实例(通过SPI接口WritableMetadataService的实例创建)initMetadataServiceExports(); //创建MetadataServiceExporter实例的集合initEventListener(); //将当前对象作为监听器加入到缓存中的监听器列表if (logger.isInfoEnabled()) {logger.info(NAME + " has been initialized!");}
}

启动服务

public DubboBootstrap start() {if (started.compareAndSet(false, true)) {ready.set(false); //设置标志值initialize();//初始化处理if (logger.isInfoEnabled()) {logger.info(NAME + " is starting...");}exportServices(); //暴露服务if (!isOnlyRegisterProvider() || hasExportedServices()) {exportMetadataService(); //暴露元数据registerServiceInstance(); //注册服务到注册中心}referServices(); //引用服务if (asyncExportingFutures.size() > 0) { //服务异步暴露后,更新启动标志new Thread(() -> {try {this.awaitFinish(); //阻塞着等待异步任务完成} catch (Exception e) {logger.warn(NAME + " exportAsync occurred an exception.");}ready.set(true);if (logger.isInfoEnabled()) {logger.info(NAME + " is ready.");}}).start();} else { //服务同步暴露后,更新启动标志ready.set(true);if (logger.isInfoEnabled()) {logger.info(NAME + " is ready.");}}if (logger.isInfoEnabled()) { //dubbo启动完成的日志logger.info(NAME + " has started.");}}return this;
}

做销毁清理

public void destroy() { //做销毁清理工作(包含关联的注册信息、元数据信息、暴露服务信息等)if (destroyLock.tryLock()) { //尝试加锁做清理,保证线程安全try {DubboShutdownHook.destroyAll(); //停机钩子线程做销毁工作if (started.compareAndSet(true, false)&& destroyed.compareAndSet(false, true)) { //在服务已启动且未销毁时,才做清理unregisterServiceInstance(); //会发起远程调用,取消注册的服务,比如若注册中心为zookeeper,则会通过curator,取消注册的服务unexportMetadataService(); //取消元数据暴露unexportServices(); //从ConfigMananer移除暴露的服务缓存unreferServices(); //取消服务引用destroyRegistries(); //销毁注册实例(即关闭注册中心客户端,以及移除注册实例在本地的缓存)DubboShutdownHook.destroyProtocols(); //销毁所有协助,并释放协议所在的资源destroyServiceDiscoveries(); //移除服务实例,即ServiceDiscovery实例clear(); //清除配置信息shutdown(); //停止运行中的线程池release(); //唤醒所有线程,将该执行的任务执行完,然后再做释放处理}} finally {destroyLock.unlock();}}
}

关联GenericEventListener类分析

主要成员变量分析

private final Method onEventMethod; //onEvent(Event)方法对应的Methodprivate final Map<Class<?>, Set<Method>> handleEventMethods; //维护着事件与事件触发的方法的关系
  • 代码解析:GenericEventListener是事件监听器,维护着事件以及触发事件的方法

主要成员方法分析

查找处理事件的方法

private Map<Class<?>, Set<Method>> findHandleEventMethods() {Map<Class<?>, Set<Method>> eventMethods = new HashMap<>();of(getClass().getMethods()).filter(this::isHandleEventMethod) //过滤出符合条件处理事件的方法.forEach(method -> {Class<?> paramType = method.getParameterTypes()[0];Set<Method> methods = eventMethods.computeIfAbsent(paramType, key -> new LinkedHashSet<>());methods.add(method);});return eventMethods;
}

执行事件对应的方法

public final void onEvent(Event event) { Class<?> eventClass = event.getClass();handleEventMethods.getOrDefault(eventClass, emptySet()).forEach(method -> {ThrowableConsumer.execute(method, m -> {m.invoke(this, event); //依次执行事件关联的方法});});
}

关联EventListener接口分析

@SPI
@FunctionalInterface
public interface EventListener<E extends Event> extends java.util.EventListener, Prioritized { //事件监听器void onEvent(E event); //事件处理static Class<? extends Event> findEventType(Class<?> listenerClass) { //根据监听器Class查找对应的事件Class(就是查找 EventListener<E extends Event> 中的泛化类型)Class<? extends Event> eventType = null;if (listenerClass != null && EventListener.class.isAssignableFrom(listenerClass)) { //isAssignableFrom判断一个类或接口是否是另一个类超类或父接口eventType = findParameterizedTypes(listenerClass).stream().map(EventListener::findEventType) //找到事件的实际类型.filter(Objects::nonNull).findAny().orElse((Class) findEventType(listenerClass.getSuperclass())); //若都没找到,则找它的父类对应的事件类型}return eventType;}static Class<? extends Event> findEventType(ParameterizedType parameterizedType) { //根据参数化的类型找到事件类型Class<? extends Event> eventType = null;Type rawType = parameterizedType.getRawType(); //获取泛型参数if ((rawType instanceof Class) && EventListener.class.isAssignableFrom((Class) rawType)) { //泛型参数为EventListener进行处理Type[] typeArguments = parameterizedType.getActualTypeArguments(); //获取实际的参数列表for (Type typeArgument : typeArguments) {if (typeArgument instanceof Class) {Class argumentClass = (Class) typeArgument;if (Event.class.isAssignableFrom(argumentClass)) { //找到类型为Event的参数eventType = argumentClass;break;}}}}return eventType;}
}
  • 代码解析:EventListener是SPI接口,也是函数式接口,通过事件监听处理对应的事件,类似Handle处理类。该接口继承了java中EventListener,因为所有事件监听器接口都必须扩展的标记接口EventListener。

问题点答疑

  • DubboBootstrap主要负责启动加载哪些信息?是从哪里进入到DubboBootStrap类的?

    • 解答:执行逻辑在DubboBootstrapApplicationListener#onApplicationContextEvent中,也就是在spring容器启动后监听容器发布的时间,里面有调用dubboBootstrap.start(); dubbo服务的启动方法
  • DubboBootstrap怎么实现优雅停机?

    • 解答:通过在创建DubboBootstrap实例时注册钩子函数,当容器停止时,对DubboBootstrap进行销毁处理,会将相关的清理操作处理,所有的任务处理完,才会关闭服务。
  • java.util.EventListener的功能用途是啥?

    • 解答:java中EventListener是一个标记接口,java规定所有的事件都要继承该接口。
  • 停机时ShutdownHookCallbacks#addCallback,是怎么进入此处的回调方法的?

    • 解答:在DubboShutdownHook#run线程被执行时,就会执行回调方法ShutdownHookCallbacks#callback,会依次执行已经注册的List钩子回调接口的callback方法

归纳总结

  • DubboBootstrap类是Dubbo的启动类,主要功能包括:
    • Config配置初始化以及合法性检查
    • 服务启动、服务注册、服务引用
    • 注册钩子、服务销毁时做清理

相关文章:

Dubbo之DubboBootstrap源码解析

功能描述 DubboBootstrap是Dubbo的启动类&#xff0c;包含服务启动、初始化、预处理配置、销毁清理等核心功能 功能分析 核心DubboBootstrap类分析 主要成员变量分析 private static volatile DubboBootstrap instance; //缓存者启动类的实例对象&#xff0c;以static形式…...

SpringBoot + Vue 微人事 项目 (第八天)

基础信息设置 在该页面添加一个大div&#xff0c;然后添加一个tab选项卡&#xff0c;Element UI里面有 把代码复制到大div里面&#xff0c;把里面的label和name属性改成我们想要的&#xff0c;再把tab-click"handleClick"去掉 <div><el-tabs v-model"a…...

人工智能引领图文扫描新趋势

1. 背景和影响 近日&#xff0c;中国大学生服务外包创新创业大赛决赛在江南大学圆满落幕。为满足现代服务产业企业的现实需求&#xff0c;本次竞赛内容设计充分聚焦企业发展中所面临的技术、管理等现实问题&#xff0c;与产业的结合度更紧密&#xff0c;智能文字识别技术是大赛…...

ChatGPT在智能城市规划和交通优化中的应用如何?

智能城市规划和交通优化是应对城市化挑战、提高城市可持续性的重要领域。在这方面&#xff0c;ChatGPT作为一种强大的自然语言处理模型&#xff0c;可以发挥重要作用&#xff0c;帮助实现更智能、高效的城市规划和交通管理。本文将详细探讨ChatGPT在智能城市规划和交通优化中的…...

探索Perfetto:开源性能追踪工具的未来之光

探索Perfetto&#xff1a;开源性能追踪工具的未来之光 1. 引言 A. 介绍Perfetto的背景和作用 随着移动应用、桌面软件和嵌入式系统的不断发展&#xff0c;软件性能优化变得愈发重要。在这个背景下&#xff0c;Perfetto作为一款开源性能追踪工具&#xff0c;日益引起了开发者…...

A*算法图文详解

基本概念 A*算法最早于1964年在IEEE Transactions on Systems Science and Cybernetics中的论文《A Formal Basis for the Heuristic Determination of Minimum Cost Paths》中首次提出。其属于一种经典的启发式搜索方法&#xff0c;所谓启发式搜索&#xff0c;就在于当前搜索…...

[MySQL] — 数据类型和表的约束

目录 数据类型 数据类型分类 数值类型 tinyint类型 bit类型 小数类型 float decimal 字符串类型 char varchar char和varchar的区别 日期和时间类型 enum 和 set 表的约束 空属性 默认值 列描述 zeorfill 主键 创建表时在字段上指定主键 删除主键&#xff1a; 追…...

JetBrains IDE远程开发功能可供GitHub用户使用

JetBrains与GitHub去年已达成合作&#xff0c;提供GitHub Codespaces 与 JetBrains Gateway 之间的集成。 GitHub Codespaces允许用户创建安全、可配置、专属的云端开发环境&#xff0c;此集成意味着您可以通过JetBrains Gateway使用在 GitHub Codespaces 中运行喜欢的IDE进行…...

LVS 负载均衡集群

集群 集群&#xff08;Cluster&#xff09;是一组相互连接的计算机或服务器&#xff0c;它们通过网络一起工作以完成共同的任务或提供服务。集群的目标是通过将多台计算机协同工作&#xff0c;提高计算能力、可用性、性能和可伸缩性&#xff0c;适用于大量高并发的场景。 集群…...

Mongodb Ubuntu安装

Mongodb Ubuntu安装 1.更新软件源导入MongoDB的GPG密钥 sudo apt update sudo apt install -y dirmngr wget gnupg apt-transport-https ca-certificates software-properties-common gnupgwget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add…...

【Spring Boot 源码学习】自动装配流程源码解析(下)

自动装配流程源码解析&#xff08;下&#xff09; 引言往期内容主要内容4. 排除指定自动配置组件5. 过滤自动配置组件6. 触发自动配置事件 总结 引言 上篇博文&#xff0c;笔者带大家了解了自动装配流程中有关自动配置加载的流程&#xff1b; 本篇将介绍自动装配流程剩余的内…...

基于微信小程序的毕业设计题目200例

个人简介&#xff1a;7 年大厂程序员经历&#xff0c;擅长Java、微信小程序、Python、Android等&#xff0c;大家有这一块的问题可以一起交流&#xff01; 各类成品 java毕设 。javaweb&#xff0c;ssh&#xff0c;ssm&#xff0c;springboot等等项目框架&#xff0c;源码丰富&…...

【数据管理】什么是数据管理?

文章目录 前言常见内容主题领域数据类型元数据引用数据主数据交易数据 数据类型的特点数据类型之间的关系GIGO数据质量评估 数据质量管理数据治理数据安全 前言 数据管理&#xff0c;即对数据资源的管理。按照 DAMA &#xff08;国际数据管理协会&#xff09;的定义&#xff1…...

[oneAPI] 手写数字识别-LSTM

[oneAPI] 手写数字识别-LSTM 手写数字识别参数与包加载数据模型训练过程结果 oneAPI 比赛&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel DevCloud for oneAPI&#xff1a;https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToolk…...

通过css设置filter 属性,使整个页面呈现灰度效果,让整个网页变灰

通过css设置filter 属性设置页面整体置灰 效果图: 通过设置 filter 属性为 grayscale(100%)&#xff0c;页面中的所有元素都会被应用灰色滤镜效果&#xff0c;使整个页面呈现灰度效果。 <style type"text/css"> html { filter: grayscale(100%); -webkit-f…...

ahooks.js:一款强大的React Hooks库及其API使用教程(一)

一、ahooks.js简介二、ahooks.js安装三、ahooks.js API介绍与使用教程1. useRequest2. useAntdTable3. useSize4. useBoolean5. useToggle6. useHover7. useDebounce8. useEventListener9. useFusionTable10. useKeyPress11. useLoading12. usePrevious13. useForm14. useUpdat…...

拟合圆算法源码(商业)

1、输入一些点 2、执行fitCircle算法 3、输出圆心(x,y)及半径r Box fitCircle(const std::vector<cv::Point2f>& points) {Box box;box.x = 0.0f;box.y = 0.0f;box.r = 0.0f;if (points.size() < 3){return box;}int i = 0;double X1 = 0;double Y1 = 0;doubl…...

第一章 IRIS 编程简介

文章目录 第一章 IRIS 编程简介简介ClassesRoutines 第一章 IRIS 编程简介 简介 IRIS 是一个高性能多模型数据平台&#xff0c;具有内置的通用编程语言 ObjectScript&#xff0c;以及对 Python 的内置支持。 IRIS 支持多进程并提供并发控制。每个进程都可以直接、高效地访问…...

Leetcode-每日一题【剑指 Offer 32 - III. 从上到下打印二叉树 III】

题目 请实现一个函数按照之字形顺序打印二叉树&#xff0c;即第一行按照从左到右的顺序打印&#xff0c;第二层按照从右到左的顺序打印&#xff0c;第三行再按照从左到右的顺序打印&#xff0c;其他行以此类推。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20…...

.NET应用UI组件DevExpress XAF v23.1 - 全新的日程模块

DevExpress XAF是一款强大的现代应用程序框架&#xff0c;允许同时开发ASP.NET和WinForms。DevExpress XAF采用模块化设计&#xff0c;开发人员可以选择内建模块&#xff0c;也可以自行创建&#xff0c;从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。 在新版中…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

HTML前端开发:JavaScript 获取元素方法详解

作为前端开发者&#xff0c;高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法&#xff0c;分为两大系列&#xff1a; 一、getElementBy... 系列 传统方法&#xff0c;直接通过 DOM 接口访问&#xff0c;返回动态集合&#xff08;元素变化会实时更新&#xff09;。…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...