前言
在之前的文章中,笔者分析过Ozone Datanode内的数据处理过程(Ozone Datanode的分布式元数据管理),包括Container,Chunk文件级别的操作处理逻辑。本文笔者继续阐述Datanode服务内部的另外一部分的处理过程:Datanode服务启动以及心跳发送给SCM服务的过程。了解此本部分过程,能更加地让我们了解Datanode服务的正常运行过程是怎样的。如文章标题所述,下面笔者将会分成2个过程进行阐述。
Ozone Datanode的服务启动
Ozone Datanode服务在名称上虽说和HDFS Datanode是同名的,但在服务本身的实现还是存在较大差异的。Ozone Datanode在这里提供的是基于Container级别的容器存储服务,被SCM服务所管理。
下面我们来看看Datanode服务的正式启动过程。总的来说,Datanode在启动过程中经历了两次的状态变化:
- 一个为Datanode State的变化
- 另一个为Datanode Running State内部的Endpoint State的变化
上面说的这2点笔者在下文中还会继续提到。这里的启动过程是这样的:
首先是Datanode service的启动,随后会启动DatanodeStateMachine daemon线程服务。
public void start() {
...
OzoneConfiguration.activate();
HddsUtils.initializeMetrics(conf, "HddsDatanode");
try {
...
datanodeStateMachine = new DatanodeStateMachine(datanodeDetails, conf,
dnCertClient, this::terminateDatanode);
try {
httpServer = new HddsDatanodeHttpServer(conf);
httpServer.start();
} catch (Exception ex) {
LOG.error("HttpServer failed to start.", ex);
}
startPlugins();
// 启动Datanode状态机线程
datanodeStateMachine.startDaemon();
} catch (IOException e) {
throw new RuntimeException("Can't start the HDDS datanode plugin", e);
} catch (AuthenticationException ex) {
throw new RuntimeException("Fail to authentication when starting" +
" HDDS datanode plugin", ex);
}
}
随后DatanodeStateMachine的start方法内会进行周期性的状态机操作执行:
/**
* Runs the state machine at a fixed frequency.
*/
private void start() throws IOException {
long now = 0;
...
// 如果Datanode当前状态不是SHUTDOWN状态,则继续进行loop循环
while (context.getState() != DatanodeStates.SHUTDOWN) {
try {
LOG.debug("Executing cycle Number : {}", context.getExecutionCount());
long heartbeatFrequency = context.getHeartbeatFrequency();
nextHB.set(Time.monotonicNow() + heartbeatFrequency);
// 执行当前Datanode状态对应应当执行的task任务,在RUNNING状态时,指的就是heartbeat任务
context.execute(executorService, heartbeatFrequency,
TimeUnit.MILLISECONDS);
now = Time.monotonicNow();
if (now < nextHB.get()) {
if(!Thread.interrupted()) {
// 睡眠等待下一次heartbeat的执行时间
Thread.sleep(nextHB.get() - now);
}
}
} catch (InterruptedException e) {
// Some one has sent interrupt signal, this could be because
// 1. Trigger heartbeat immediately
// 2. Shutdown has be initiated.
} catch (Exception e) {
LOG.error("Unable to finish the execution.", e);
}
}
...
}
进入上面的context的execute方法,
public void execute(ExecutorService service, long time, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
stateExecutionCount.incrementAndGet();
// 1)获取当前状态对应的task
DatanodeState<DatanodeStateMachine.DatanodeStates> task = getTask();
// Adding not null check, i