<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">花了两天的时间终于把eclipse-Hadoop的开发环境建立起来了,中间也遇到了很多问题,有十分崩溃的时候,不过庆幸最后问题也都解决了.</span>
第一天晚上熬夜到四点解决问题遇到坎之后真心是痛恨程序员这个职业啊,不过最后将WordCount跑起来之后还是相当开心的。功夫不负苦心人!
下面讲一下自己遇到的几个虐心的问题以及解决方法,望给遇到相似问题的人提供一下参考。
问题1:Hadoop在安装时的文件配置。
由于我安装的是最新版的Hadoop-2.7.1,但是网上关于最新版的安装资料很少,很多都是关于hadoop一点几和零点几的,hadoop安装过程中有四个最重要的文件需要配置:
core-site.xml
mapred-site.xml
yarn-site.xml
hdfs-site.xml
关于这四个文件的配置如下(建议最好能根据自己安装的版本看一下官网的特定版本的安装教程,里面讲的很详细,很多问题都是因为没有阅读官网教程直接照搬网上的出现的):
core-site.xml. master是你的主节点的ip,9000是namenode端口
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/home/hadoop/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
</configuration>
mapred-site.xml. 将jobtracker的端口设置为9001,这个在后面搭建eclipse开发环境的时候要用到
<configuration>
<property>
<name>mapreduce.job.tracker</name>
<value>hdfs://master:9001</value>
<final>true</final>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master:19888</value>
</property>
</configuration>
hdfs-site.xml. 这里在dfs.replication的value我设置的是2,意思是设置集群Block的备份数为2.
<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>master:50090</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/home/hadoop/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/home/hadoop/dfs/data</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
</configuration>
yarn-site.xml. 这个配置有点多,主要是对nodemanager以及resourcemanager的一些配置,网上关于这个的配置基本一致
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>master:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>master:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>master:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>master:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>master:8088</value>
</property>
</configuration>
以上四个文件是Hadoop最重要的四个配置文件,关于另外的文件的配置可以参考网上其他教程
问题2:为什么hadoop集群跑起来之后没有出现jobtracker和tasktracker进程。
Hadoop-2.7.1跑起来后在master下用Jps命令查看进程应该如下:
注意,这里没有出现JobTracker是因为我们现在使用的是2.7.1版本的hadoop,这个版本使用了yarn作为Hadoop的全局资源管理器。同样在slave下用jps查看进程则会出现:
这里也不会出现TaskTracker,关于这两个进程是老版本的hadoop安装时才会出现的,hadoop的新手一定要在参考教程安装时注意这个问题。
我就是因为没有注意到这个问题一致以为自己安装错了,最后看官网2.7.1的教程才知道是因为yarn的关系。
yarn将JobTracker的功能拆分到了两个单独的守护进程中,一个全局资源管理器ResourceManager,有调度器和应用程序管理器组成。还有一个支持特定应用程序的应用程序主节点
Application Master。事实上,到这一步我们的hadoop就已经安装好了,可以跑起来了。
问题3:关于eclipse-hadoop-2.7.1的插件问题。
关于网上的eclipse-hadoop-2.x的插件对于2.7貌似用不了,这个插件貌似2.2,2.4和2.6版本下不会出什么问题,因此可以选择自己用这个自己编译一个适合自己hadoop版本的插件,亦或是在网上搜一个特定的。关于2.7.1版本的插件链接:linux下jdk1.8 hadoop-eclipse-plugin-2.7.1
问题4:配置map/reduce master 和DFS master的host 和port。
这部分第一个是jobtracker的配置,在mapred-site.xml文件中,对于我的配置来说port就是9001,第二个就是core-site.xml中的配置,对于我的配置来说port就是9000。host应该填写namenode的IP,对于我来说就是master。
问题5:运行word count输入的input和output目录路径。
这里在参数输入路径的时候最好带上hdfs的地址,hdfs://master:9000/input hdfs://master:9000/output.
以上,大功告成,运行wordcount程序:
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
public class WordCount {
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
if (otherArgs.length != 2) {
System.err.println("Usage: wordcount <in> <out>");
System.exit(2);
}
Job job = new Job(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}