Flink JobMaster 调度源码分析1:调度过程

Flink JobMaster 调度源码分析1:调度过程
Flink JobMaster 调度源码分析2:Slot 分配策略
Flink JobMaster 调度源码分析3:Physical Slot 分配过程
本文分析的源码为flink 1.18.0_scala2.12版本。

调度

调度代码可查看 flink-runtime 模块中的 org.apache.flink.runtime.scheduler 包。
DefaultScheduler 继承 SchedulerBase,具有方法 startScheduling()。

startScheduling()
-> startSchedulingInternal()
	-> // 这里有不同的调度策略
	schedulingStrategy.startScheduling() 
		->  // 以 PipelinedRegionSchedulingStrategy 为例(以流水线区域的粒度调度任务)
		maybeScheduleRegions(sourceRegions) // 从源算子开始调度
			-> this::scheduleRegion
				-> schedulerOperations.allocateSlotsAndDeploy();

通过 allocateSlotsAndDeploy() 方法为每个示例分配 slot,并在返回 slot 时部署算子实例。只有在所有算子实例都分配到 slot 后,才会部署。将按照给定的拓扑顺序去部署。只接受处于创建状态的算子实例。下面是 DefaultScheduler.allocateSlotsAndDeploy() 代码。(其中 Execution 是执行一个 ExecutionVertex 的一次尝试。当发生故障或者数据需要重算的情况下 ExecutionVertex 可能会有多个 ExecutionAtemptID。一个 Execution 通过 ExecutionAtemptID 来唯一标识。JM 和 TM 之间关于 task 的部署和 task status 的更新都是通过 ExecutionAttemptID 来确定消息接受者。)

// 将 vertices 转换为 Execution
final List<Execution> executionsToDeploy =  
        verticesToDeploy.stream()  
                .map(this::getCurrentExecutionOfVertex)  
                .collect(Collectors.toList());  
// 部署 Execution
executionDeployer.allocateSlotsAndDeploy(executionsToDeploy, requiredVersionByVertex);

在 executionDeployer.allocateSlotsAndDeploy() 中,通过下面代码分配 slot。

@Override  
public void allocateSlotsAndDeploy(  
        final List<Execution> executionsToDeploy,  
        final Map<ExecutionVertexID, ExecutionVertexVersion> requiredVersionByVertex) {  
	// 确定所有 Execution 都已被创建,即状态为 CREATED
	validateExecutionStates(executionsToDeploy);  
	// 将 Execution 状态转换为 SCHEDULED
	transitionToScheduled(executionsToDeploy);  
	// 为每个 Execution 分配 slot
    final Map<ExecutionAttemptID, ExecutionSlotAssignment> executionSlotAssignmentMap =  
            allocateSlotsFor(executionsToDeploy);  
    final List<ExecutionDeploymentHandle> deploymentHandles =  
            createDeploymentHandles(  
                    executionsToDeploy, requiredVersionByVertex, executionSlotAssignmentMap);  
	// 部署实例
    waitForAllSlotsAndDeploy(deploymentHandles);  
}

继续查看 allocateSlotsFor(executionsToDeploy) 的调用过程。

allocateSlotsFor(executionsToDeploy)
-> executionSlotAllocator.allocateSlotsFor(executionAttemptIds)
// executionSlotAllocator 可以是 SimpleExecutionSlotAllocator 或 SlotSharingExecutionSlotAllocator

1. 调度策略

系统已经实现的分配策略有:SimpleExecutionSlotAllocator、SlotSharingExecutionSlotAllocator。
自己实现分配策略,需要实现接口 ExecutionSlotAllocator,需要实现下面的方法。

Map<ExecutionAttemptID, ExecutionSlotAssignment> allocateSlotsFor(  
        List<ExecutionAttemptID> executionAttemptIds);

分配策略是在创建 JobMaster 过程中,创建调度器时指定的,具体代码位置如下。
使用哪个分配策略是在 ExecutionDeployer(如DefaultExecutionDeployer) 创建时指定的。ExecutionDeployer 在 Scheduler(如DefaultScheduler) 构造函数中创建。代码如下。

// 创建 slot 分配策略
this.executionSlotAllocator =  
		// executionSlotAllocatorFactory 是构造函数中传递的 slot 分配策略
        checkNotNull(executionSlotAllocatorFactory)  
                .createInstance(new DefaultExecutionSlotAllocationContext());  
......
// 创建 ExecutionDeployer
this.executionDeployer =  
        executionDeployerFactory.createInstance(  
                log,  
                executionSlotAllocator,  
                executionOperations,  
                executionVertexVersioner,  
                rpcTimeout,  
                this::startReserveAllocation,  
                mainThreadExecutor);

executionSlotAllocatorFactory 是在 DefaultSchedulerFactory 构造函数中通过下面语句获得

return new DefaultScheduler(
		......
		schedulerComponents.getAllocatorFactory(),  // 指定了分配策略
		......
		)

schedulerComponents 的出现位置仍然在当前构造函数中。

final DefaultSchedulerComponents schedulerComponents =  
        createSchedulerComponents(  
                jobGraph.getJobType(),  
                jobGraph.isApproximateLocalRecoveryEnabled(),  
                jobMasterConfiguration,  
                slotPool,  
                slotRequestTimeout);

查看其调用过程

final DefaultSchedulerComponents schedulerComponents = createSchedulerComponents(......);
-> return createPipelinedRegionSchedulerComponents(......);
	-> final ExecutionSlotAllocatorFactory allocatorFactory = new SlotSharingExecutionSlotAllocatorFactory(......);

也就是说,在上面代码中,指定了 SlotSharingExecutionSlotAllocatorFactory 做为 slot 分配策略。至于 SimpleExecutionSlotAllocator,当前代码查看结果是,该类是在批处理中使用的。

2. slot 选择

在指定 slot 分配策略时,同样对 SlotSelectionStrategy 进行了选择,代码如下。

// 由物理节点提供 slot 的策略
final SlotSelectionStrategy slotSelectionStrategy =  
        SlotSelectionStrategyUtils.selectSlotSelectionStrategy(  
                jobType, jobMasterConfiguration);  
......
// 根据 slotSelectionStrategy 创建 physicalSlotProvider,用于后续分配 slotfinal PhysicalSlotProvider physicalSlotProvider =  
        new PhysicalSlotProviderImpl(slotSelectionStrategy, slotPool);

进入 SlotSelectionStrategyUtils.selectSlotSelectionStrategy() 中,可以看到涉及到两个配置项:ClusterOptions.EVENLY_SPREAD_OUT_SLOTS_STRATEGY 和 CheckpointingOptions.LOCAL_RECOVERY。
EVENLY_SPREAD_OUT_SLOTS_STRATEGY 是 Flink 中的一种资源分配策略,用于控制 TaskManager 如何分配其 slots。这种策略确保了作业的各个任务能够均匀地分布在所有的 TaskManager 上,从而提高任务的并行处理能力。在Flink的配置文件中,可以通过设置 slotmanager.slot-allocator.type 属性为 EVENLY_SPREAD_OUT 来启用这种策略。
如果使用了该策略,则 SlotSelectionStrategy 为 EvenlySpreadOutLocationPreferenceSlotSelectionStrategy,否则为 DefaultLocationPreferenceSlotSelectionStrategy
LOCAL_RECOVERY 用于指示 Flink 是否应该从最后一个成功的检查点恢复。如果启用,Flink 会尝试从最后一个成功的检查点自动恢复,并可能回滚在该检查点之后开始的所有更改。如果指定了该选项,则 SlotSelectionStrategy 为 PreviousAllocationSlotSelectionStrategy

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值