今天在调试mapred streaming脚本时,发生了非常奇怪的问题:mapred脚本在被tasktracker调用后总是会随机的失败,错误信息如下:
java.lang.RuntimeException: java.lang.NullPointerException at org.apache.Hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:325) at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:545) at org.apache.hadoop.streaming.PipeReducer.reduce(PipeReducer.java:95) at org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:518) at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:419) at org.apache.hadoop.mapred.Child$4.run(Child.java:259) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:396) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1059) at org.apache.hadoop.mapred.Child.main(Child.java:253) Caused by: java.lang.NullPointerException at org.apache.hadoop.streaming.PipeMapRed$MRErrorThread.setStatus(PipeMapRed.java:522) at org.apache.hadoop.streaming.PipeMapRed$MRErrorThread.run(PipeMapRed.java:454)
从错误信息中,我们可以知道:错误并不是mapred脚本错误导致的,而是在tasktracker初始化mapred脚本时tasktracker发生了内部错误最初以为是集群服务器某些系统资源不够导致的错误,但是查看集群其他正在运行的任务后,确并没有发现和上面同样的问题,其他正在运行的任务完全没有抛出上面的错误。现在可以肯定是我的mapred脚本的问题,考虑到我再mapred脚本中使用的redis,而我的redis接口包是我自己在redis-py的基础上修改而来(redis-py不支持python2.4版本),怀疑是不是redis-py的包引发上述问题,于是屏蔽掉代码中使用redis模块的代码,再次运行mapred,结果还是发生了同样的问题。
没办法,只好再仔细对比正常的mapred脚本和我现在又问题的mapred脚本之间的差异,发现和正常的mapred脚本相比,现在的代码多出了一句向jobtarcker汇报mapred脚本运行状态的代码:
sys.stderr.write("reporter:status:output\n")
虽然理论上这条语句不应该会导致上述奇怪的问题发生,但是还是死马当活马医试试看,屏蔽掉mapred脚本中的这条代码,重新运行mapred脚本,奇迹发生了,一切正常,没有任何错误发生;重新再加上redis操作的代码,再次运行mapred脚本,还是没有错误发生。看来,问题的元凶就是这条向jobtracker汇报状态的代码:sys.stderr.write("reporter:status:output\n")
上述错误 应该是tasktracker中的一个小bug,不知道是否有人提交了这个bug?马上我们的集群就要升级到hadoop1.0.3,到时候在hadoop1.0上再测试测试