背景
发现线上偶尔会出现一些Spark Task会显示Schedule Delay数分钟甚至十几分钟,所以要排查原因。
Task 时间分析以及Schedule Delay计算公式

如图所示,时间轴上面的表示Driver 记录到的各个时间,时间轴下面的表示Executor记录到的各个时间。
我们反过来,先说 Executor 记录的各个时间,再说Driver记录的各个时间。
Executor 中Task运行时间
Task 在Executor端运行,有三个时间段,分别是 deserializeTime, executorRunTime, serializeTime。(很奇怪,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。 因为代码风格问题,在偏前段的代码中,改名叫 resultFetchStart, gettingResultTime 被重新定义为函数 = {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后的那一个时间段出现了问题。
预知后续分析,且听下回分解~~
本文探讨了Spark中Task的ScheduleDelay现象,分析了Task在Executor端的运行时间,包括deserializeTime、executorRunTime和serializeTime,并介绍了Driver端的相关时间指标。通过计算ScheduleDelayTime,定位了可能的问题区域。
1764

被折叠的 条评论
为什么被折叠?



