情景:
编程环境: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,使用的参数可能会明确一些。