应用程序主机在收到作业的最后一个任务已完成的通知时,会将作业的状态更改为“成功”。然后,当作业轮询状态时,它得知作业已成功完成。因此, waitForCompletion()
方法会返回一条消息,以告诉用户任务已成功完成。此时会打印作业、统计信息和计数器。如果应用程序主机配置为这样做,它还会发送 HTTP 作业通知。使用mapreduce.job.end-notification.url
属性,客户端希望接收可以配置它的回调。最后,任务容器和应用程序主在完成工作后清理它们的工作状态。因此, OutputCommitter's commitJob()
方法被调用,中间输出被删除。如果需要,为了允许用户稍后询问,作业信息由作业历史服务器存档。
失败案例?
真实的用户代码可能会崩溃,可能会充满错误,甚至机器可能会失败。 Hadoop 处理此类故障的能力是使用它的最大好处,它允许作业成功完成。以下任何组件都可能失败:
- 应用大师
- 节点管理器
- 资源管理器
- 任务
其中最常见的是任务失败。当用户在reduce 任务或map 任务中编写代码时,运行时异常是最常发生的这种故障。如果发生这种情况,JVM 会在退出之前向其父应用程序主机报告错误。该错误最终会出现在用户日志中。应用程序释放容器,以便在将任务尝试标记为失败后,其资源可用于另一个任务。
为了流式传输任务,如果流式处理以非零退出代码退出,则将流式处理标记为失败。 stream.non.zero.exit.is.failure
属性(默认为 true)控制此行为。任务突然退出,JVM 是另一种故障模式,可能是由于 MapReduce 用户代码的暴露,存在 JVM 错误,导致 JVM 在特定情况下退出。节点管理器注意到进程已退出。因此,它可以在通知应用程序主机时将尝试标记为失败。挂起的任务的处理方式不同。 Application master 继续将任务标记为失败,并注意到它有一段时间没有收到进度更新。在这段时间之后,任务 JVM 进程将被自动杀死。 mapreduce.task.timeout
属性设置为以毫秒为单位的值,可以在每个作业的基础上配置超时时间。在此任务之后,任务被视为失败通常是 10 分钟。长时间运行的任务永远不会被标记为失败,因为将超时值设置为零会禁用超时。随着时间的推移,可能会导致集群速度变慢,挂起的任务永远不会释放它的容器。因此,为了确保任务定期报告进度就足够了,应该避免这种方法。应用程序主机将在收到任务尝试通知后重新安排任务的执行。任务失败后,应用主节点会尽量避免在节点管理器上重新调度任务。如果任务失败四次,则不会再次重试。该值可配置为控制任务的最大数量。它由减少任务mapreduce.reduce.maxattempts
和地图任务的mapreduce.map.maxattempts
默认情况下,如果任何任务失败四次,则整个作业都会失败。如果一些任务失败,则中止某些应用程序的作业是不可取的,因为尽管有一些失败,但仍可以使用作业的结果。无需触发,可以为作业设置作业失败。使用mapreduce.map.failures.maxpercent
mapreduce.reduce.failures.maxpercent
属性映射任务和化简任务是独立控制的。任务被杀死与失败不同。由于推测性重复或节点管理器正在运行,任务尝试也可能被终止。 mapreduce.map.maxattempts
和mapreduce.reduce.maxattempts
任务不会根据运行任务的尝试次数计算被杀死的任务尝试。