Spark Task的各个动作时间来源以及Task Schedule Delay 问题排查

背景

发现线上偶尔会出现一些Spark Task会显示Schedule Delay数分钟甚至十几分钟,所以要排查原因。

Task 时间分析以及Schedule Delay计算公式

在这里插入图片描述

如图所示,时间轴上面的表示Driver 记录到的各个时间,时间轴下面的表示Executor记录到的各个时间。
我们反过来,先说 Executor 记录的各个时间,再说Driver记录的各个时间。

Executor 中Task运行时间

Task 在Executor端运行,有三个时间段,分别是 deserializeTimeexecutorRunTimeserializeTime。(很奇怪,Task 并没有选择和Driver端一样的方式,直接计算各个阶段的起止时间,而是选择将各个阶段的运行耗时计算好,再通过 metrics 返回给Driver。这种方式潜在的给我们这次问题排查造成了第一个麻烦。如果不能确定Task的真正开始和结束时间,那么我们就没办法确定Task Delay 发生在哪一个阶段了。)

  • deserializeTime: 表示Task获取Task后,进行反序列化的时间。 计算公式:task.metrics.setExecutorDeserializeTime(TimeUnit.NANOSECONDS.toMillis((taskStartTimeNs - deserializeStartTimeNs) + task.executorDeserializeTimeNs)) 包含两部分,task = ser.deserialize[Task[Any]](taskDescription.serializedTask, classLoader)val (rdd, func) = ser.deserialize[(RDD[T], (TaskContext, Iterator[T]) => U)](ByteBuffer.wrap(taskBinary.value), classLoader)
  • executorRunTime: 表示Task 执行时间,不包含上面的 deserializeTime 时间,也不包含下面的对结果序列化的 serializeTime 时间。计算公式: task.metrics.setExecutorRunTime(TimeUnit.NANOSECONDS.toMillis((taskFinishNs - taskStartTimeNs) - task.executorDeserializeTimeNs))
  • serializeTime: 表示Task直接结果在发往Driver之前,进行序列化的时间。 计算公式: task.metrics.setResultSerializationTime(TimeUnit.NANOSECONDS.toMillis(afterSerializationNs - beforeSerializationNs))

Driver中Task运行时间

  • LaunchTime: 在 TaskSetManager 中,也叫 resourceOfferTime ,即 taskSet.offerTask() 成功后,开始运行 Task 的时间
  • LaunchDelay: 表示 从Stage被提交到当前Task被调度的时间,计算公式: taskInfo.launchTime - stage.submissionTime
  • finishTime: Driver最后标识该Task生命周期结束的时间, 具体是从 handleSuccessTask(taskSet, tid, serializedData) 进入 markFinished() 的时间
  • gettingResultTime: 如果我们的 Task 返回的结果比较大,Task结果返回的方式是 IndirectTaskResult,Driver 会在记录开始调用 fetchIndirectTaskResult() 进行读取结果的时间。(实际上应该还包括对读取的数据的deserialize 时间)。如果是 DirectTaskResult ,该时间为 0。 因为代码风格问题,在偏前段的代码中,改名叫 resultFetchStartgettingResultTime 被重新定义为函数 = {launchTime + duration - fetchStart }
  • duration: = finishTime - launchTime

Schedule Delay Time

我们直接用UI页面(AppStatusUtils)的Schedule Delay Time 公式来分析

gettingResultTime = launchTime + duration - fetchStart
schedulerDelay =  math.max(0, 
	duration - runTime - deserializeTime - serializeTime - gettingResultTime
	)

所以这里得到的就是上图中的两个粉红色的时间范围。通过分析Executor 的 Task 运行日志,初步判定,是Task运行结束,上报RPC到Driver后的那一个时间段出现了问题。

预知后续分析,且听下回分解~~

猜你喜欢

转载自blog.csdn.net/wankunde/article/details/121403842