前言

本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系

正文

TaskScheduler 的核心任务是提交 TaskSet 到集群运算并汇报结果。

( 1 )为 TaskSet 创建和维护一个 TaskSetManager ,并追踪任务的本地性以及错误信息。

( 2 )遇到 Straggle 任务时,会放到其他节点进行重试。

( 3 )向 DAGScheduler 汇报执行情况,包括在 Shuffle 输出丢失的时候报告 fetch failed 错误等信息。

TaskScheduler 源码类注释 (3.2.0-SNAPSHOT)

/**
 * 低层次的任务调度器接口,目前由 TaskSchedulerImpl 独家实现。
 * 
 * 此接口允许插入不同的任务调度程序。
 * 
 * 每个 TaskScheduler 为单个 SparkContext 安排任务。
 * 
 * 这些调度器从每个阶段的 DAGScheduler 中获取提交给它们的任务集,并负责将任务发送到集群、运行它们、在出现故障时重试以及减轻 straggle。
 * 
 * 它们将事件返回给 DAGScheduler。
 */
private[spark] trait TaskScheduler

TaskSchedulerImpl 源码类注释 (3.2.0-SNAPSHOT)

/**
 * 通过 SchedulerBackend 为多种类型的集群调度任务。
 * 
 * 它还可以通过使用 LocalSchedulerBackend 并将 isLocal 设置为true来使用本地设置。
 * 
 * 它处理常见的逻辑,如确定作业之间的调度顺序、唤醒以启动推测性任务等。 
 * 
 * 客户端应该首先调用initialize() 和start(),然后通过 submitTasks 方法提交任务集。 
 * 
 * 线程:SchedulerBackends 和任务提交客户端可以从多个线程调用此类,因此它需要公共API方法中的锁来维护其状态。
 * 
 * 另外,一些 SchedulerBackends 要在这里发送事件时会自动同步,然后获取对我们的锁定,因此我们需要确保在锁定自己时不会尝试锁定后端。
 * 
 * 这个类是从许多线程调用的,特别是:
 * 
 * * The DAGScheduler Event Loop
 * * The RPCHandler threads, 用来响应 Executors 的状态更新。
 * * 周期性地恢复来自 CoarseGrainedSchedulerBackend 的所有供给,以适应延迟调度
 * * task-result-getter threads
 * 
 * 注意:Spark-RPC 框架中抛出的任何非致命异常都可能被吞没。
 * 
 * 因此,在resourceOffers、statusUpdate 等方法中引发异常不会使应用程序失败,但可能导致未定义的行为。
 * 
 * 相反,我们应该使用类似 TaskSetManger.abort() 的方法中止一个阶段,然后使应用程序失败(SPARK-31485)。
 * 
 * 延迟调度:延迟调度是一种为了提高集群和工作负载吞吐量而牺牲数据局部性的作业公平性的优化。
 * 
 * “延迟”的一个有意义的定义是自任务集使用其公平的资源份额以来经过了多少时间。
 * 
 * 由于在没有完全模拟的情况下计算此延迟是不切实际的,因此使用的启发式方法是 TaskSetManager 上次启动任务后的时间,
 * 
 * 并且自上次提供其“公平份额”以来,没有因延迟调度而拒绝任何资源。
 * 
 * 当 resourceOffers 的参数“isAllFreeResources”设置为true时,启用“公平共享”。
 * 
 * “延迟调度拒绝”是指尽管存在挂起的任务(在TaskSetManager中实现),但资源未被利用的情况。
 * 
 * 传统的启发式方法只测量 TaskSetManager 上次启动任务以来的时间,可以通过将 spark.locality.wait.legacyResetOnTaskLaunch 设置为 true 来重新启用。
 */
private[spark] class TaskSchedulerImpl
上一篇 下一篇