使用线程池时,Hadoop'Filesystem关闭'异常

时间:2013-03-12 21:26:15

标签: exception hadoop filesystems mapreduce threadpool

我是hadoop的新手,我在5节点集群上运行多个mapReduce作业。运行多个线程时,我已经开始获得“文件系统关闭”异常。当一次运行一个工作时,工作正常。在映射之后,在减少之前出现错误。它看起来像这样:

java.lang.Exception: java.io.IOException: Filesystem closed
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:399)
Caused by: java.io.IOException: Filesystem closed
at org.apache.hadoop.hdfs.DFSClient.checkOpen(DFSClient.java:552)
at org.apache.hadoop.hdfs.DFSInputStream.readWithStrategy(DFSInputStream.java:648)
at org.apache.hadoop.hdfs.DFSInputStream.read(DFSInputStream.java:706)
at java.io.DataInputStream.read(Unknown Source)
at org.apache.hadoop.util.LineReader.readDefaultLine(LineReader.java:209)
at org.apache.hadoop.util.LineReader.readLine(LineReader.java:173)
at org.apache.hadoop.mapreduce.lib.input.LineRecordReader.nextKeyValue(LineRecordReader.java:167)
at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:526)
at org.apache.hadoop.mapreduce.task.MapContextImpl.nextKeyValue(MapContextImpl.java:80)
at org.apache.hadoop.mapreduce.lib.map.WrappedMapper$Context.nextKeyValue(WrappedMapper.java:91)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:143)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:756)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:338)
at org.apache.hadoop.mapred.LocalJobRunner$Job$MapTaskRunnable.run(LocalJobRunner.java:231)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

这不会一直发生,如果我重新执行失败的作业,它将正常运行。不幸的是,这花费了太多时间。我假设这与访问相同输入文件的多个任务有关,当一个任务完成时,它关闭所有任务的输入文件。如果这是我想知道的问题是如何覆盖这个问题。我尝试在mapper中重写清理以重新打开路径,但这看起来很愚蠢并且不起作用。

@Override 
public void cleanup(Context context){
        Job tempJob;
        try {
            tempJob = new Job();
            Path fs = ((FileSplit) context.getInputSplit()).getPath();
            FileInputFormat.addInputPath(tempJob, fs);
            System.out.println("Finished map task for " + context.getJobName());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

我也想知道这是否是使用线程池执行hadoop mapReduce作业的基本问题。谢谢你的任何想法。

编辑:当我提到乔布斯和任务时,我可能有点不清楚。我实际上是用自己的映射器和缩减器运行多个作业。这些作业中的每一个都将为我正在创建的特定表生成一列。说一笔钱或一笔数。每个作业都有自己的线程,并且它们都访问相同的输入文件。我遇到的问题是,当一些工作完成后,他们将抛出'Filesystem closed Exception'。如果可能有所作为,我也在使用Yarn。

1 个答案:

答案 0 :(得分:1)

作为一般规则,除非您的CPU工作量非常大,否则我不建议在同一任务中使用多个线程,这会增加JVM中出现问题的可能性,并且重新运行任务的成本会更高。您应该考虑增加地图任务的数量,当然每个任务都将在一个单独的JVM中运行,但它更加清晰。

如果您真的想要采用多线程方式,那么我怀疑您使用了错误类型的映射器,对于多线程应用程序,您应该使用MultithreadedMapper它具有run方法的不同实现,并且应该是线程安全的。您可以像这样使用它:

job.setMapperClass(MultithreadedMapper.class);

您可以指定这样的线程数:

int numThreads = 42;
MultithreadedMapper.setNumberOfThreads(numThreads);