ES源码二:集群启动过程

昨天 5828阅读 0评论

命令行参数解析

Elasticsearch:
ES源码二:集群启动过程 第1张
在main里面创建了Elasticsearch实例,然后调用了main方法,这个main方法最终会调用到父类Command的main方法
ES源码二:集群启动过程 第2张

这里做了几件事:

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

ES源码二:集群启动过程 第3张

  1. 解析命令行参数

ES源码二:集群启动过程 第4张

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

ES源码二:集群启动过程 第5张

  1. 加载elasticsearch.yml配置文件

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

  1. 验证配置

ES源码二:集群启动过程 第6张

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

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

阶段二主要是在Bootstrap类中进行的,我们进入到Bootstrap.init方法中看
ES源码二:集群启动过程 第7张
这个方法特别长,主要做了这样几件事:

  1. 创建BootStrap对象

ES源码二:集群启动过程 第8张

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

ES源码二:集群启动过程 第11张

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

ES源码二:集群启动过程 第12张

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

ES源码二:集群启动过程 第13张

  1. 创建pid文件

ES源码二:集群启动过程 第14张

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

ES源码二:集群启动过程 第15张

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

ES源码二:集群启动过程 第16张
ES源码二:集群启动过程 第17张

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

ES源码二:集群启动过程 第18张

  1. 初始化本地资源:

ES源码二:集群启动过程 第19张
ES源码二:集群启动过程 第20张
本地资源初始化主要包括:

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

    除了调用initializeNatives方法进行本地资源初始化,还调用initializeProbes() 进行初始化探针操作,主要用于操作系统负载监控、jvm 信息获取、进程相关信息获取。
    ES源码二:集群启动过程 第21张

    1. 注册关闭资源的 ShutdownHook

    ES源码二:集群启动过程 第22张

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

    ES源码二:集群启动过程 第23张

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

    ES源码二:集群启动过程 第24张

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

    ES源码二:集群启动过程 第25张

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

    ES源码二:集群启动过程 第26张

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

    ES源码二:集群启动过程 第27张

    节点实例启动

    节点创建

    之前只是简单的看了一下Node的创建,再回顾一下:
    ES源码二:集群启动过程 第28张
    后续在构造方法里面一共做了这样几件事:

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

    ES源码二:集群启动过程 第29张
    ES源码二:集群启动过程 第30张

    1. 各种信息的打印:

    ES源码二:集群启动过程 第31张

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

    ES源码二:集群启动过程 第32张

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

    ES源码二:集群启动过程 第33张

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

    ES源码二:集群启动过程 第34张

    1. 创建线程池:

    ES源码二:集群启动过程 第35张
    ES线程池的实现封装在ThreadPool中。ThreadPool中定义了4种线程池类型:
    ES源码二:集群启动过程 第36张

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

      ThreadPool中创建了多个线程池,主要有以下几种:
      ES源码二:集群启动过程 第37张

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

      ES源码二:集群启动过程 第38张

      action的类型定义在ActionType:
      ES源码二:集群启动过程 第39张

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

      ES源码二:集群启动过程 第40张

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

      ES源码二:集群启动过程 第41张
      ES源码二:集群启动过程 第42张
      ES源码二:集群启动过程 第43张

      1. 初始化HTTP Handler

      ES源码二:集群启动过程 第44张

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

      节点启动

      Node.start主要负责启动各个生命周期组件(LifecycleComponent)和从Guice(也就是injector)中获取需要启动的服务类实例,然后调用它们的start方法
      ES源码二:集群启动过程 第45张
      并且后面是一堆server要启动:
      ES源码二:集群启动过程 第46张

      总结一下:

      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 方法。
      ES源码二:集群启动过程 第47张


免责声明
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明。
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所
提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何
损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在
转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并白负版权等法律责任。

手机扫描二维码访问

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,5828人围观)

还没有评论,来说两句吧...

目录[+]