ES源码二:集群启动过程

news2025/3/12 1:21:42

命令行参数解析

Elasticsearch:
image.png
在main里面创建了Elasticsearch实例,然后调用了main方法,这个main方法最终会调用到父类Command的main方法
image.png

这里做了几件事:

  1. 注册一个 ShutdownHook,其作用就是在系统关闭的时候捕获IOException并且进行输出

image.png

  1. 解析命令行参数

image.png

  1. 加载多个路径:data、home、logs,这里会调用到子类EnvironmentAwareCommand的execute方法,将配置解析成hashmap,并且确认 es.path.data、es.path.home、es.path.logs 这几个路径设置的存在,最后调用createEnv方法加载elasticsearch.yml配置文件,在调用Elasticsearch.execute方法

image.png

  1. 加载elasticsearch.yml配置文件

createEnv 函数最终调用了 InternalSettingsPreparer.prepareEnvironment 来加载 elasticsearch.yml 配置文件,并且创建了 command 运行的环境:Environment 对象

  1. 验证配置

image.png

总结一下第一阶段:解析命令行参数并且验证配置

资源检查和本地资源初始化

阶段二主要是在Bootstrap类中进行的,我们进入到Bootstrap.init方法中看
image.png
这个方法特别长,主要做了这样几件事:

  1. 创建BootStrap对象

image.png

  1. 加载elasticsearch.keystore 安全配置:在ES运行后,在config目录会生成一个elasticsearch.keystore文件,这个文件是用来保存一些敏感配置的。因为ES大多数配置都是明文保存的,但是像X-Pack中的security配置需要进行加密保存,所以这些配置信息就是保存到elasticsearch.keystore中。image.pngimage.png
  2. 创建一个新的Environment:根据保存初始化配置的initialEnv和安全配置keystore调用createEnvironment(最终调用prepareEnvironment方法)重新创建一个运行ES必须的环境

image.png

  1. 设置节点名称:这里设置节点的名字,可以在后续的日志输出中使用,否则只要只要ID可用就会使用节点ID(节点ID可读性不好)

image.png

  1. 加载log4j2配置:会加载log4j2.properties文件中的相关配置,然后配置log4j的属性。

image.png

  1. 创建pid文件

image.png

  1. 检查Lucene jar:通过版本号来检查lucene是否被替换掉了,如果被替换无法被启动

image.png

  1. 为创建Node对象实例做准备工作:通过调用INSTANCE.setup(true, environment)为创建Node实例对象做一些准备工作,下面几步我们进入到INSTANCE.setup(true, environment)

image.png
image.png

  1. 为给定模块生成控制器守护程序:尝试为每个模块(modules目录下的模块)生成native控制器守护进程的。

image.png

  1. 初始化本地资源:

image.png
image.png
本地资源初始化主要包括:

  • 不能以root运行
  • 尝试启动系统调用过滤器
  • 尝试调用mlockall,mlockall会将进程使用的部分或者全部的地址空间都锁定在物理内存中,防止其被交换到swap空间
  • 如果是运行在window的话,关闭事件的监听器
  • 尝试设置最大线程数、最大虚拟内存、最大文件size
  • 为lucene设置一个随机的seed

除了调用initializeNatives方法进行本地资源初始化,还调用initializeProbes() 进行初始化探针操作,主要用于操作系统负载监控、jvm 信息获取、进程相关信息获取。
image.png

  1. 注册关闭资源的 ShutdownHook

image.png

  1. 通过调用 JarHell.checkJarHell 检查是否有重复的类。

image.png

  1. 在Debug 模式下以 ifconfig 格式输出网络信息

image.png

  1. 加载安全管理器,进行权限认证:通过调用Security.configure 函数进行安全管理器加载,进行权限认证操作:

image.png

  1. 创建Node实例对象:根据加载的运行环境创建Node实例,也快要进入第三个阶段了

image.png

  1. 启动Node节点:回到了之前set up的地方,然后调用start方法,进行node节点的启动

image.png

节点实例启动

节点创建

之前只是简单的看了一下Node的创建,再回顾一下:
image.png
后续在构造方法里面一共做了这样几件事:

  1. 设置节点的生命周期:将生命周期设置为INITIALIZED,此时节点正处于初始化状态

image.png
image.png

  1. 各种信息的打印:

image.png

  1. 创建插件服务:主要是加载modules目录中的模块和加载plugins目录中已经安装的插件

image.png

  1. 设置格外的节点角色:

image.png

  1. 创建NodeEnvironment:NodeEnvironment实例话的过程中会生成Node ID,最后此处打印节点相关的信息,需要注意的是,此处会通过 Environment.assertEquivalent 函数来保证启动过程中配置没有被更改

image.png

  1. 创建线程池:

image.png
ES线程池的实现封装在ThreadPool中。ThreadPool中定义了4种线程池类型:
image.png

  • direct:执行器不支持关闭的线程
  • fixed:拥有固定线程的线程池,当一个任务无法分配一条线程时会被排队
  • fixed_auto_queue_size:和fixed类似,但是任务队列会根据 Little’s Law 自动调整。8.0 后将被移除。
  • scaling, 线程池中线程的数量可变,线程的数量在 core 和 max 间变化,使用 keep_alive 参数可以控制线程在线程池中的空闲时间。

ThreadPool中创建了多个线程池,主要有以下几种:
image.png

  1. 创建NodeClient实例:NodeClient执行本地的action的。

image.png

action的类型定义在ActionType:
image.png

  1. 创建各个模块和服务:各个模块和服务的创建

image.png

  1. **绑定对应的对象到Guice:将实例化的对象绑定要ModulesBuilder中,最后调用 modules.createInjector 创建 injector(注入器)。ES 用到了 **Guice这个谷歌提供的轻量级 IOC 库,bind 和 createInjector 是其提供的基本功能。

image.png
image.png
image.png

  1. 初始化HTTP Handler

image.png

后续就是节点启动的流程了

节点启动

Node.start主要负责启动各个生命周期组件(LifecycleComponent)和从Guice(也就是injector)中获取需要启动的服务类实例,然后调用它们的start方法
image.png
并且后面是一堆server要启动:
image.png

总结一下:

  1. 启动各个生命周期组件和服务,一些重点的服务如下:
服务简介
IndicesService负责索引管理,如创建、删除等操作。
IndicesClusterStateService负责根据各种集群索引状态信息进行相应的操作,如创建或者恢复索引(这些实际的操作会交给具体的模块实现)等。
SnapshotsService负责创建快照,在执行快照创建和删除的时候,所有的执行步骤都在主节点上=进行。
SnapshotShardsService此服务在 data node 上运行,并且控制此节点上运行中的分片快照。其负责开启和停止分片级别的快照。
RepositoriesService负责维护节点快照存储仓库和提供对存储仓库的访问。
SearchService提供搜索支持的服务。
ClusterService集群管理服务,负责管理集群状态、处理集群任务、发布集群状态等。
FsHealthService文件系统健康检查服务。通过创建一个临时文件来检查文件系统是否可写。
MonitorService负责提供操作系统、进程、JVM、文件系统级别的监控服务
NodeConnectionsService该组件负责维护从该节点到集群状态中列出的所有节点的连接,并在节点从集群状态中删除后断开与节点的连接。并且会定期检查所有链接是否在打开状态,并且在需要的时候恢复它们。需要注意的是此组件不负责移除节点!
GatewayService网关服务,负责集群元数据的持久化和恢复。
Discovery节点发现模块是一个可插拔的模块,其负责发现集群中其他的节点,发布集群状态到所有节点,选举主节点和发布集群状态变更事件。
PeerRecoverySourceService负责处理对等分片的恢复请求,并且开启从这个源分片到目标分片的恢复流程。
TransportService负责节点间数据同步。
HttpServerTransport提供 REST 接口服务。
  1. 调用ClusterService.setNodeConnectionService将NodeConnectionService绑定到ClusterService中去
  2. 调用acceptIncomingRequests 尝试接收请求。
  3. 调用discovery.startInitialJoin 开始进行加入集群的循环
  4. 开启线程去检查是否已经加入集群
  5. HttpServerTransport,并且绑定监听地址,接收 REST 请求

4.集群启动流程

  1. Master 选举

根据前面的内容可知,Master 对集群的重要性,所以集群中多个节点启动后首要的任务是选举出一个 Master,有了 Master 后续的集群启动操作将由 Master 主导。

  1. 选择集群元数据

在 Master 被选举出来后,其首要任务就是要选择出集群的元数据信息,这部分的工作主要在 Gateway 模块中处理。Master 会向已经加入到集群的所有节点获取各种的元数据信息,然后选择出版本号最新的那个作为集群的元数据,并向所有节点进行广播。

  1. Allocation

在 allocation 过程中将会选择 shard 级别的元数据信息,并且构建内容路由表。在集群启动的时候,所有的 shard 都是未分配的,allocation 会决定哪个 shard 被分配到哪个节点,并且把这个关系记录下来写入到内容路由表。
我们知道 ES 的分片分为主分片和副分片,所以在分配的时候会先选择出主分片,然后再选择出副分配。

  1. 索引恢复(recovery )

为了保证数据的可靠性,在启动的时候主分片需要执行 recovery 流程来恢复没有来得及刷盘的数据。而副分片除了要恢复没有刷盘的数据外,还要恢复主分片已经写入但是副分片还没有写入的数据来保证数据的一致性。
集群的启动主要就是上述的几大流程,经过这些流程后,一般来说集群就可以提供对外的服务了。

5.总结

通过 Elasticsearch 这个类,系统进行了命令行参数解析与配置加载。通过 Bootstrap 类进行了资源检查与本地资源初始化。最后实例化了 Node 类,其负责加载各个模块和插件、创建线程池、创建 keepalive 线程等工作,在 Node.start 方法中获取了各个服务的实例并且调用它们的 start 方法。
image.png

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

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

相关文章

配置路由器实现互通

1.实验环境 实验用具包括两台路由器(或交换机),一根双绞线缆,一台PC,一条Console 线缆。 2.需求描述 如图6.14 所示,将两台路由器的F0/0 接口相连,通过一台PC 连接设备的 Console 端口并配置P地址(192.1…

基于栈求解迷宫的单条路径和所有路径

数据结构与算法课的一个实验,记录一下。 单纯想要了解利用栈求解迷宫的算法可以直接跳转到相应的小标题。 完整代码链接code_2024/mazeLab LeePlace_OUC/code - 码云 - 开源中国 (gitee.com) 文章目录 要求栈的实现MazeType类型的组织迷宫的初始化和销毁打印路径…

死磕GMSSL通信-java/Netty系列(二)

死磕GMSSL通信-java/Netty系列(二) 在上一篇文章中,我们探讨了如何利用C/C++实现国密通信。而本文将聚焦于Java环境下,特别是基于Netty框架,如何实现与国密系统的安全通信。为了确保新项目遵循最新的国密标准,我们将优先推荐使用GB/T 38636-2020(TLCP)协议。对于Java开…

python 如何使用windows系统自带的定时功能运行脚本

亲测此定时可以在电脑重启后,仍会自动运行 1.搜索栏搜索‘任务’,打开任务计划程序,点击创建任务 2.写一下任务名称和描述 3.选择触发器,点新建,可以创建定时计划 4.默认只有一次,每天,每月&am…

BackTrader 中文文档(二十七)

原文:www.backtrader.com/ 数据 - 多个时间框架 原文:www.backtrader.com/blog/posts/2015-08-24-data-multitimeframe/data-multitimeframe/ 有时,使用不同的时间框架进行投资决策: 周线用于评估趋势 每日执行进入 或者 5 分钟…

解决 MSYS2 Qt 6.7 默认 stylesheet 在 windows 11 下的显示故障

项目场景: MSYS2 升级到 Qt6.7.0,发现显示故障,所有Qt6程序以及 QtCreator的SpinBox都显示不全,Combox的底色不对。 问题描述 2024年4月1日,pacman升级MSYS2后,Qt6遇到风格错误。如果使用官方的 Qt onlin…

CSS设置内外边距

目录 内边距(paddingj): 前言: 设置内边距: 外边距(margin): 前言: 设置外边距: 补充(折叠): 内边距(padding)&#…

【程序分享】bopcalc 程序:一种评估分子动力学模拟中键序参数的高效方法(二)

分享一篇使用一种评估键序参数的高效程序:bopcalc 。 感谢论文的原作者! 主要内容 “ 我们提出了一种新颖、高效的方法来评估键序参数 (BOP)。我们的方法利用球谐函数和 Wigner 符号的特性来减少 BOP 表达式中的项数,并采用归一化关联勒让德…

APP测试基本流程以及APP测试要点梳理,保证您看了不后悔!

🔥 交流讨论:欢迎加入我们一起学习! 🔥 资源分享:耗时200小时精选的「软件测试」资料包 🔥 教程推荐:火遍全网的《软件测试》教程 📢欢迎点赞 👍 收藏 ⭐留言 &#x1…

使用Pandas解决问题:对比两列数据取最大值的五种方法

目录 一、使用max方法 二、使用apply方法结合lambda函数 三、使用np.maximum函数 四、使用clip方法 五、使用where方法结合条件赋值 总结: 在数据处理和分析中,经常需要比较两个或多个列的值,并取其中的最大值。Pandas库作为Python…

前端大屏项目适配方法

要在F11全屏模式下查看 方法一,rem font-size 动态设置HTML根字体大小 和 body 字体大小(lib_flexible.js) 将设计稿的宽(1920)平均分成 24 等份, 每一份为 80px。HTML字体大小就设置为 80 px&#xff…

OSPF大型实验

OSPF大型实验 实验拓扑图 实验思路 1、R4为ISP,其上只配置IP地址;R4与其他所直连设备间均使用公有IP; 2、R3-R5、R6、R7为MGRE环境,R3为中心站点; 3、整个OSPF环境IP基于172.16.0.0/16划分;除了R12有两…

智慧园区可视对讲广播解决方案

智慧园区可视对讲广播解决方案 目前而言智慧园区管理者主要需要解决的问题是: 1.面对庞大的园区小区规模,能源管理全部依赖人工已经无法实现; 2.节能管理工作难度大,面对问题,没有好的解决方案; 3.面临…

详解电源测试系统自定义报告模板功能:如何轻松实现数据导出

在NSAT-8000电源测试系统内,数据一般分为三级架构:原始数据、数据报告和数据分析。数据报告可以直接展示出电源模块的各项测试数据和测试结果,帮助用户评估电源性能,为电源的优化提升提供数据支持。 系统的记录报告板块展示着历史…

油价年内第五涨,92汽油正式进入8元时代

今天是2024年4月16日,最新消息!据国家发改委网站16日消息,根据近期国际市场油价变化情况,按照现行成品油价格形成机制,自2024年4月16日24时起,也就是今晚过完的零点开始,国内汽、柴油价格&#…

计算机网络:MAC地址 IP地址 ARP协议

计算机网络:MAC地址 & IP地址 & ARP协议 MAC地址IP地址ARP协议 MAC地址 如果两台主机通过一条链路通信,它们不需要使用地址就可以通信,因为连接在信道上的主机只有他们两个。换句话说,使用点对点信道的数据链路层不需要使…

FR107-ASEMI快恢复二极管FR107

编辑:ll FR107-ASEMI快恢复二极管FR107 型号:FR107 品牌:ASEMI 封装:DO-41 最大平均正向电流(IF):1A 最大循环峰值反向电压(VRRM):1000V 最大正向电压…

当当图书网数据采集分析:10万条数据的深入洞察

基于搜索结果,我将为您提供一个关于当当图书网数据采集的文章框架,假设我们已经有了10万条数据的采集结果。请注意,由于没有具体的数据文件,以下内容将是一个示例性的框架,您可以根据实际采集到的数据进行填充和调整。…

LeetCode: 209 长度最小的子数组

209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1…

C#创建磁性窗体的方法:创建特殊窗体

目录 一、磁性窗体 二、磁性窗体的实现方法 (1)无标题窗体的移动 (2)Left属性 (3)Top属性 二、设计一个磁性窗体的实例 (1)资源管理器Resources.Designer.cs设计 (2)公共类Frm_Play.cs (3)主窗体 …