对于使用Hadoop进行日志分析等工作的开发者来说,相信一直都面临着一个非常头疼的问题。那就是:对hadoop的mapreduce作业,在分布式集群上进行单个task的单步debug跟踪调试无法办到。只能在本地进行调试,然后提交到集群中运行,但是集群中如果某个task总是失败,要对这一个task进行单步跟踪就非常困难。其实原因很简单,因为当把作业提交到hadoop 集群进行运行的时候,你事先根本就不知道那个map或者reduce的task会被分配到哪个tasktracker上执行。所以过去的两年里,写 mapreduce应用的工程师们一直面临着这个悬而未决的问题。只能通过在程序中加日志,并在作业完成或者失败后追踪日志来进行问题定位。无法达到对程序象调试单机程序一样的进行调试。
其实在hadoop中,有一个好东西,利用这个好东西,就可以实现在集群中对某个task进行单步调试的需求。这个东西就是 IsolationRunner。IsolationRunner是一个小工具,能够在tasktracker机器上,重新单独运行失败的task,这样对于某些大作业(比如job的输入有100TB),如果因为某一个task重复失败而导致整个job失败,就不用连续不断的提交job,进行复现,然后定位某个task失败的原因,这样做的代价就会非常的大。如果能够对失败的task进行单独执行,那么要定位问题的原因代价就变得很小,对工程师来说也非常的方便。
要想对失败的task进行单独重跑,肯定是有前提的,大家知道,对于map而言,其输入数据是来自分布式文件系统(通常是HDFS)中输入数据的某个 split,所以如果想要重跑map task,其输入数据就需要被保留下来。同样对于reduce而言,其输入是从所有map的中间结果shuffle到该reduce的数据,如果想要重跑 reduce task,这些数据也就需要保留下来。所以为了提供对失败的task进行单独重跑的功能,作业执行过程中的中间结果,或者每个map的输入数据对应的 split数据,就需要被保留下来。为此hadoop提供了一个作业的配置选项:keep.failed.task.files,该选项默认为 false,表示对于失败的task,其运行的临时数据和目录是不会被保存的,这也是hadoop在支持这项功能前默认的做法,因为如果失败的task的临时文件和目录被保留的过多,会占据tasktracker上过多的磁盘空间和文件数,造成磁盘浪费。而当将 keep.failed.task.files选项设置为true(注意:该配置选项是一个per job的配置),那么hadoop在执行该job时,当发生map fail或者reduce fail时,就会将task能够单独重跑的所有环境都保留下来,比如task运行时对应的job.xml,map input对应的split.dta文件,或者reduce的输入file.out文件。这样,要重跑一个map或者reduce task的环境就已经具备。
如何重跑:
当fail的task环境具备以后,就可以对单独的task进行重跑了。重跑的方式为: