Spark源码分析之八:Task运行(二)

本文深入分析Spark Task的运行流程,包括Task内存管理器TaskMemoryManager、Task的run()方法及TaskContext的创建。讨论了ResultTask和ShuffleMapTask的runTask()方法,以及RDD的iterator()函数在数据处理中的作用。此外,还涉及了反序列化过程和内存管理的关键环节。
摘要由CSDN通过智能技术生成

        在《Spark源码分析之七:Task运行(一)》一文中,我们详细叙述了Task运行的整体流程,最终Task被传输到Executor上,启动一个对应的TaskRunner线程,并且在线程池中被调度执行。继而,我们对TaskRunner的run()方法进行了详细的分析,总结出了其内Task执行的三个主要步骤:

        Step1:Task及其运行时需要的辅助对象构造,主要包括:

                       1、当前线程设置上下文类加载器;

                       2、获取序列化器ser;

                       3、更新任务状态TaskState;

                       4、计算垃圾回收时间;

                       5、反序列化得到Task运行的jar、文件、Task对象二进制数据;

                       6、反序列化Task对象二进制数据得到Task对象;

                       7、设置任务内存管理器;

        Step2:Task运行:调用Task的run()方法,真正执行Task,并获得运行结果value
        Step3:Task运行结果处理:

                       1、序列化Task运行结果value,得到valueBytes;

                       2、根据Task运行结果大小处理Task运行结果valueBytes:

                            2.1、如果Task运行结果大小大于所有Task运行结果的最大大小,序列化IndirectTaskResult,IndirectTaskResult为存储在Worker上BlockManager中DirectTaskResult的一个引用;

                            2.2、如果 Task运行结果大小超过Akka除去需要保留的字节外最大大小,则将结果写入BlockManager,Task运行结果比较小的话,直接返回,通过消息传递;

                            2.3、Task运行结果比较小的话,直接返回,通过消息传递。

        大体流程大概就是如此。我们先回顾到这里。那么,接下来的问题是,任务内存管理器是什么?如何计算开始垃圾回收时间?Task的run()方法的执行流程是什么?IndirectTaskResult,或者BlockManager又是如何传递任务运行结果至应用程序即客户端的?

        不要着急,我们一个一个来解决。

        关于任务内存管理器TaskMemoryManager,可以参照《Spark源码分析之九:内存管理模型》一文,只要知道它是任务运行期间各区域内存的管理者就行,这里不再赘述。

        接下来,我们重点分析下Task的run()方法,看看Task实际运行时的处理逻辑。其代码如下:

/**
   * Called by [[Executor]] to run this task.
   * 被Executor调用以执行Task
   *
   * @param taskAttemptId an identifier for this task attempt that is unique within a SparkContext.
   * @param attemptNumber how many times this task has been attempted (0 for the first attempt)
   * @return the result of the task along with updates of Accumulators.
   */
  final def run(
    taskAttemptId: Long,
    attemptNumber: Int,
    metricsSystem: MetricsSystem)
  : (T, AccumulatorUpdates) = {
  
    // 创建一个Task上下文实例:TaskContextImpl类型的context
    context = new TaskContextImpl(
      stageId,
      partitionId,
      taskAttemptId,
      attemptNumber,
      taskMemoryManager,
      metricsSystem,
      internalAccumulators,
      runningLocally = false)
      
    // 将context放入TaskContext的taskContext变量中
    // taskContext变量为ThreadLocal[TaskContext]
    TaskContext.setTaskContext(context)
    
    // 设置主机名localHostName、内部累加器internalAccumulators等Metrics信息
    context.taskMetrics.setHostname(Utils.localHostName())
    context.taskMetrics.setAccumulatorsUpdater(context.collectInternalAccumulators)
    
    // task线程为当前线程
    taskThread = Thread.currentThread()
    
    if (_killed) {// 如果需要杀死task,调用kill()方法,且调用的方式为不中断线程
      kill(interruptThread = false)
    }
    
    try {
      // 调用runTask()方法,传入Task上下文信息context,执行Task,并调用Task上下文的collectAccumulators()方法,收集累加器
      (runTask(context), context.collectAccumulators())
    } finally {
      // 上下文标记Task完成
      context.markTaskCompleted()
      
      try {
        Utils.tryLogNonFata
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值