当ES集群更新配置、升级版本时,需要通过“kill”ES进程来关闭节点。
::ES进程会捕获SIGTERM信号(kill命令默认信号)进行处理,调用各模块的stop方法停止服务并安全退出。::
- 如果主节点被关闭,集群会重新选主,在这个期间集群会进入短暂的无主状态。
- 如果数据节点被关闭,则读写请求的TCP连接也会关闭,对客户端来说写操作执行失败,但写流程已经达到Engine流程的会正常写入,只是客户端无法感知结果。此时客户端重试,如果使用自动生成 ID,则数据内容会重复。
综合来说,滚动升级产生的影响是中断当前读写请求,以及主节点重启可能引起的分片分配过程。
4.1 关闭流程分析
每个模块的Service中都实现了doStop和doClose方法,用于处理这个模块的正常关闭。
节点总的关闭流程位于Node#close,在close方法的实 现中,先调用一遍各个模块的doStop,然后再次遍历各个模块执行 doClose。
各模块的关闭有一定的顺序,stop方法执行顺序如下:
- ResourceWatcherService 通用资源监视
- HttpServerTransport HTTP传输服务(Rest接口服务)
- SnapshotsService 快照服务
- SnapshotShardsService shard快照服务(负责启动和通知shard级快照)
- IndicesClusterStateService 收集状态信息后处理其中索引相关操作
- Discovery 集群拓扑管理
- RoutingService 处理reroute(节点之间迁移shard)
- ClusterService 集群管理服务(处理集群任务、发布集群状态)
- NodeConnectionsService 节点连接管理服务
- MonitorService 提供进程级、系统级、文件系统和JVM的监控服务
- GatewayService 负责集群元数据持久化与恢复
- SearchService 处理搜索请求
- TransportService 底层传输服务
- plugins 当前的所有插件
- IndicesService 负责创建、删除索引等操作
综合来看,关闭顺序大致如下:
- 关闭快照和HTTPServer,不再响应用户REST请求。
- 关闭集群拓扑管理,不再响应ping请求。
- 关闭网络模块,让节点离线。
- 执行各个插件的关闭流程。
- 关闭IndicesService。
最后关闭IndicesService,是因为这期间需要等待释放的资源最多,时间最长。
4.2 分片读写过程中执行关闭
4.2.1 写入过程中关闭
线程在写入数据时,会对Engine加写锁。
IndicesService的doStop方法对本节点上全部索引并行执行removeIndex, 当执行到Engine的flushAndClose(先flush然后关闭Engine),也会对Engine加写锁。由于写入操作已经加了写锁,此时写锁会等待,直到写入执行完毕。因此数据写入过程不会被中断。但是由于网络模块被关闭,客户端的连接会被断开。客户端应当作为失败处理,虽然ES服务端 的写流程还在继续。
4.2.2 读取过程中关闭
线程在读取数据时,会对Engine加读锁。 flushAndClose时的写锁会等待读取过程执行完毕。
但是由于连接被关 闭,无法发送给客户端,导致客户端读失败。
节点关闭过程中,IndicesService的doStop对Engine设置了超时,如果flushAndClose一直等待,则CountDownLatch.await默认1天才会继续后面的流程。
4.3 主节点被关闭
节点正常执行关闭流程,当TransportService模块被关闭后,集群重新选举新Master。
4.4 总结
- 节点启动流程做初始化和检查工作,各个子模块启动后异步开始工作如: 加载本地数据、选主、加入集群等。
- 节点在关闭时也有机会处理已经收到的请求,但是写完后或许无法返回客户端,线程池中未执行完的任务在超时时间之内也会继续执行。
- ::集群健康从Red到Green的时间主要是消耗在维护主副分片的一致性上::。