发现线上偶尔会出现一些Spark Task会显示Schedule Delay数分钟甚至十几分钟,所以要排查原因。
Task 时间分析以及Schedule Delay计算公式如图所示,时间轴上面的表示Driver 记录到的各个时间,时间轴下面的表示Executor记录到的各个时间。
我们反过来,先说 Executor 记录的各个时间,再说Driver记录的各个时间。
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))
- 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
我们直接用UI页面(AppStatusUtils)的Schedule Delay Time 公式来分析
gettingResultTime = launchTime + duration - fetchStart schedulerDelay = math.max(0, duration - runTime - deserializeTime - serializeTime - gettingResultTime )
所以这里得到的就是上图中的两个粉红色的时间范围。通过分析Executor 的 Task 运行日志,初步判定,是Task运行结束,上报RPC到Driver后的那一个时间段出现了问题。
预知后续分析,且听下回分解~~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)