文章目录
Checkpoint的触发方式有两种
- 一种是数据源节点中的Checkpoint操作触发,通过CheckpointCoordinator组件进行协调和控制。 CheckpointCoordinator通过注册定时器的方式按照
配置的时间间隔触发数据源节点的Checkpoint操作
。数据源节点会向下游算子发出Checkpoint Barrier事件,供下游节点使用。- 另一种是下游算子节点
根据上游发送的Checkpoint Barrier事件控制算子中Checkpoint操作的触发时机
,即只有接收到所有上游Barrier事件后,才会触发本节点的Checkpoint操作。
本文先介绍通过CheckpointCoordinator触发算子的Checkpoint操作
CheckpointCoordinator在整个作业中扮演了Checkpoint协调者
的角色,负责在数据源节点触发Checkpoint以及整个作业的Checkpoint管理,并且CheckpointCoordinator组件会接收TaskMananger在Checkpoint执行完成后返回的Ack消息。
一. 启动CheckpointCoordinator
当作业的JobStatus转换为Running时,通知CheckpointCoordinatorDeActivator监听器启动CheckpointCoordinator服务。
如代码CheckpointCoordinatorDeActivator.jobStatusChanges()方法主要包含如下逻辑。
> 1. 当`newJobStatus == JobStatus.RUNNING`时,立即调用
> coordinator.startCheckpointScheduler()方法启动整个Job的调度器
> CheckpointCoordinator,此时Checkpoint的触发依靠CheckpointCoordinator进行协调。
>
> 2. 当JobStatus为其他类型状态时,调用coordinator.stopCheckpointScheduler()方法,
> 停止当前Job中的Checkpoint操作。
public class CheckpointCoordinatorDeActivator implements JobStatusListener {
private final CheckpointCoordinator coordinator;
public CheckpointCoordinatorDeActivator(CheckpointCoordinator coordinator) {
this.coordinator = checkNotNull(coordinator);
}
@Override
public void jobStatusChanges(JobID jobId,JobStatus newJobStatus, long timestamp,
Throwable error) {
if (newJobStatus == JobStatus.RUNNING) {
// 启动Checkpoint调度程序
coordinator.startCheckpointScheduler();
} else {
// 直接停止CheckpointScheduler
coordinator.stopCheckpointScheduler();
}
}
}
二. 开启CheckpointScheduler线程
接下来在CheckpointCoordinator.startCheckpointScheduler()方法中调用scheduleTriggerWithDelay()方法进行后续操作,向创建好的checkpointCoordinatorTimer线程池添加定时调度执行的Runnable线程。
如代码所示:
在CheckpointCoordinator.scheduleTriggerWithDelay()方法中指定baseInterval参数,设定执行Checkpoint操作的时间间隔,通过定时器周期性地触发ScheduledTrigger线程,Checkpoint的具体操作在ScheduledTrigger线程中实现。
private ScheduledFuture<?> scheduleTriggerWithDelay(long initDelay) {
return timer.scheduleAtFixedRate(
new ScheduledTrigger(),
initDelay, baseInterval, TimeUnit.MILLISECONDS);
}
三. 触发Checkpoint
如代码,ScheduledTrigger也是CheckpointCoordinator的内部类,实现了Runnable接口。在ScheduledTrigger.run()方法中调用了CheckpointCoordinator.triggerCheckpoint()方法触发和执行Checkpoint操作。
private final class ScheduledTrigger implements Runnable {
@Override
public void run() {
try {
// 调用triggerCheckpoint()方法触发Checkpoint操作
triggerCheckpoint(System.currentTimeMillis(), true);
}
catch (Exception e) {
LOG.error("Exception while triggering checkpoint for job {}.", job, e);
}
}
}
CheckpointCoordinator.triggerCheckpoint()方法包含的执行逻辑非常多,这里重点介绍其中的主要逻辑。根据CheckpointCoordinator触发Checkpoint操作的过程分为以下几个部分。
1. Checkpoint执行前的工作
- 首先检查Checkpoint的执行环境和参数,满足条件后触发执行Checkpoint操作。Checkpoint执行过程分为异步和同步两种:
调用preCheckBeforeTriggeringCheckpoint()方法进行一些前置检查,主要包括检查CheckpointCoordinator当前的状态是否为shutdown、Checkpoint尝试次数是否超过配置的最大值。
- 构建执行和触发Checkpoint操作对应的Task节点实例的Execution集合,其中tasksToTrigger数组中存储了触发Checkpoint操作的ExecutionVertex元素,实际上就是所有的数据源节点。
CheckpointCoordinator仅会触发数据源节点的Checkpoint操作,其他节点则是通过Barrier对齐的方式触发的。
- 构建需要发送Ack消息的ExecutionVertex集合,主要是从tasksToWaitFor集合中转换而来。
tasksToWaitFor中存储了ExecutonGraph中所有的ExecutionVertex,也就是说
每个ExecutionVertex节点对应的Task实例都需要向CheckpointCoordinator中汇报Ack消息
。
// 主要做前置检查
synchronized (lock) {
preCheckBeforeTriggeringCheckpoint