使用 TotalOrderPartitioner 时,抛出异常:File _partition.lst does not exist

情景:

    编程环境:Hadoop-1.2.1;使用NEW API

    如下边代码,TotalOrderPartitioner.setPartitionFile(...) 后,在 TotalOrderPartitioner 的 setConf(...) 方法中抛出异常  java.io.FileNotFoundException: File _partition.lst does not exist.  

job.setPartitionerClass(TotalOrderPartitioner.class); 
	
InputSampler.RandomSampler<IntWritable, NullWritable> sampler = 
new InputSampler.RandomSampler<IntWritable, NullWritable>(0.1, 10000, 10);
	
Path partitionFile = new Path(input, "_partitions");
TotalOrderPartitioner.setPartitionFile(conf, partitionFile);
InputSampler.writePartitionFile(job, sampler);    .......

    查看结果发现,采样的结果没有写入到 partitionFile 中。而是写入到 /user/{user_name}/_partition.lst 的文件里面。

通过 Eclipse 调试,找到在 下边的函数

InputSampler.writePartitionFile(job, sampler);

代码里面:

public static <K,V> void writePartitionFile(Job job, Sampler<K,V> sampler) // InputSampler.writePatitionFile(...)
      throws IOException, ClassNotFoundException, InterruptedException {
    Configuration conf = job.getConfiguration();
    final InputFormat inf = 
        ReflectionUtils.newInstance(job.getInputFormatClass(), conf);
    int numPartitions = job.getNumReduceTasks();
    K[] samples = sampler.getSample(inf, job);
    LOG.info("Using " + samples.length + " samples");
    RawComparator<K> comparator =
      (RawComparator<K>) job.getSortComparator();
    Arrays.sort(samples, comparator);
    Path dst = new Path(TotalOrderPartitioner.getPartitionFile(conf));
    FileSystem fs = dst.getFileSystem(conf);
    if (fs.exists(dst)) {
      fs.delete(dst, false);
    }
    ...
}
第 03 行:通过 job.getConfiguration() 获取的 conf 配置对象
第 12 行:获取的 Path dst 也不是 我设置的路径


原因:

    可以跑一下下面的代码:

Configuration conf = new Configuration();
Job job = new Job(conf);
TotalOrderPartitioner.setPartitionFile(conf, partitionFile); 
String pf = TotalOrderPartitioner.getPartitionFile( conf );
System.out.println("pf: " + pf);
pf = TotalOrderPartitioner.getPartitionFile( job.getConfiguration() );
System.out.println("pf2: " + pf);

会得到不一样的结果。

具体为什么 conf  与 job.getConfiguration() 根本上有什么区别,还要进一步对源代码进行学习。


解决方法:

方法一:

    查看了 InputSampler.writePartitionFile(...); 源码发现其中使用的是:jog。getConfiguration conf = job.getConfiguration();

所以在main函数里面就要使用:

TotalOrderPartitioner.setPartitionFile( job.getConfiguration(), partitionFile); 

方法二(我没测试过,可以试试):

    使用Old API,使用的参数可能会明确一些。

 

猜你喜欢

转载自blog.csdn.net/xzx735/article/details/25649945