elasticsearch 启动流程

elasticsearch 启动流程

elasticsearch 启动流程

启动脚本执行:


org.elasticsearch.bootstrap.Elasticsearch start
如果有-d参数,添加: <&- & 关闭标准输入并后台运行。

主线程执行的启动流程大概做了三部分工作:加载配置、检查外部环境和内部环境、初始化内部资源。最后启动各个子模块和keepalive线程

解析配置


包括命令行参数、主配置文件,log配置文件

启动keepAive线程,初始化运行环境


主线程执行完启动流程后会退出,keepalive线程是唯一的用户线程,作用是保持进程运行,java程序当没有用户线程是进程会退出。
初始化运行环境包括根据解析的配置准备各资源路径,初始化日志系统,创建pid文件,检查es.max-open-files

JVM检测


JVM运行模式检查:client、server,ES对效率要求较高,建议使用server模式,否则打印警告;

JVM版本的检查:如果是Oracle,检查版本对应JVM_OPTS必要参数,如果是IBM,版本要求2.8以上。

系统相关初始化


是否root权限启动:可以调整配置文件运行以root权限启动,但是不建议.

是否使用seccomp模式:linux 2.6.23之后支持的sandboxing机制,让进程运行在“安全模式”,只能执行四种系统调用:read,write,exit,sigreturn,只能使用已打开的fd,如果尝试其他系统调用,内核会使用SIGKILL终止进程。

是否启用mlockall:避免使用swap,建议开启

内部初始化


初始化两种probes:ProcessProbe和OsProbe,提供进程和OS层面的信息

添加shutdown hook,当JVM关闭时调用node.close

jar hell检测:类重复校验

构建node实例:根据设置构建node
ModulesBuilder modules = new ModulesBuilder();
modules.add(new XXXModule(this.settings));

启动系统


调用node.start()启动节点,调用keepAliveThread.start()启动用户线程

加入集群流程


获取集群node列表
在UnicastZenPing构造函数中,向discovery.zen.ping.unicast.hosts配置的节点列表发送请求,获取到DiscoveryNode列表

findMaster
通过UnicastZenPing发送ping,从response信息中找到master,如果没有master,进入选主流程

不同角色执行不同任务
nodeFD是一个Runnable(一个任务),被选为master的时候启动:
onElectedAsMaster()->nodesFD.updateNodesAndPing(state);
masterFD在第一次收到master的cluster state信息的时候启动:
handleNewClusterStateFromMaster()->masterFD.restart();

Transport模块启动流程


节点之间通讯、节点与客户端之间通讯(包括java api和rest api)等所有网络数据传输默认都是transport模块实现的。
transport模块分为LocalTransport和NettyTransport两种,默认是第二种,底层用的是Netty:基于NIO的客户、服务器端编程框架
总体架构:

TransportRequest层有五种类型的请求,在节点之间的TCP长连接上传输,默认情况下,每个节点都会与集群的其他节点保持13个TCP连接,每个连接根据不同类型的业务用作固定的用途。这13个连接分别是:

  • recovery 数据恢复使用,默认:2
  • bulk 批量请求使用,默认:3
  • reg ,默认类型,如:请求加入集群,集群数据同步。默认:6
  • state ClusterState信息等,默认:1
  • ping ,用作nodeFD或masterFD的ping,默认:1

配置加载

从解析的配置文件中获取:

workerCount
工作线程数,serverBootstrap和clientBootstrap都会创建大小为workerCount的线程池,默认为CPU数量x2,ES5.1之后的版本 限制为最大32.因为在CPU核心数很多的机器上占用非常多内存。

connectionsPerNode
每种请求的连接数

receiveBufferSizePredictorFactory
确定接收缓冲大小。默认最大512k,根据配置的transport.netty.receive_predictor_min和transport.netty.receive_predictor_max确定使用固定大小还是动态大小

启动

根据配置(IP、端口、socket选项等)创建一个ClientBootstrap和若干个ServerBootstrap(都是Netty中的)。然后分别设置各自的PipelineFactory。

PipelineFactory是Netty中的概念,Netty中,Channel是通讯的载体(一个连接),ChannelHandle负责Channel中的处理逻辑,ChannlePipeline可以理解成ChannleHandler的容器,一个Channel包含一个ChannelPipeline,所有ChannelHandler都会注册到ChannelPipeline中。

ServerBootstrap默认构建1个,监听127.0.0.1:9300,可以根据不同请求类型绑定不同地址端口:
节点之间的通讯

client到节点直接的通讯

自动发现数据通讯

主要流程如下图:

建立到集群其他节点的链接

TCP服务已监听,有哪些客户端会连接进来取决于运行时逻辑。
TCP客户端已准备好,本节点启动过程中,探测到集群的节点信息后, 调用
transportService.connectToNode()->NettyTransport.ConnectToNodes()
连接到其他node,一个连接就是一个Netty中的Channel:

发送request
sendRequest封装了向节点发送数据的流程。首先根据目标节点和type(上面五种之一)选择一个连接(channle),根据选项看情况压缩数据,通过CompressorFactory.defaultCompressor().streamOutput创建一个带压缩的StreamOutput,写入version和action,写入request,转换成ChannelBuffer,调用targetChannel.write(buffer);发送数据

消息处理
如果某个模块需要监听收到的消息进行处理,他需要调用transportService.registerRequestHandler为不同的action注册不同的handle;如果一个模块要发送请求,他也需要提供一个handle准备处理Response。在NettyTransport类中,依据Netty的ChannelHandle处理机制,两个处理类被注册到Netty的ChannelPipeline中:
SizeHeaderFrameDecoder 负责处理消息头,检查非法请求,去掉头部数据
MessageChannelHandler 负责处理消息体,在messageReceived函数中判断是否需要解压,根据是否request调用handleRequest或handleResponse进行处理。

总体流程:

handleRequest过程
从收到的数据中解析出action,根据action获取对应的 handle,handle在TransportService.requestHandlers中注册。交给对应的handle处理

handleResponse过程
根据requestId获取handle,handle在TransportService.clientHandlers中注册。

(转载请注明作者和出处 easyice.cn ,请勿用于任何商业用途)

1 Star2 Stars3 Stars4 Stars5 Stars (欢迎评分)
Loading...

2 thoughts on “elasticsearch 启动流程

发表评论

电子邮件地址不会被公开。 必填项已用*标注