基于Ubuntu在Hadoop的环境下调用MapReduce对文件中各个单词出现次数进行统计
一般来说,如果要做服务器可选择CentOS或者Ubuntu Server;如果做桌面系统可选择Ubuntu Desktop。在学习Hadoop方面,虽然两个系统没有多大区别,但在此次实验中使用 Ubuntu 14.04 64位 作为系统环境。(可参考使用VirtualBox安装Ubuntu).
64位Ubuntu推荐下载地址: 点击下载.
装好了 Ubuntu 系统之后,在安装 Hadoop 前还需要做一些必备工作。
1、创建hadoop用户
如果你安装 Ubuntu 的时候不是用的 “hadoop” 用户,那么需要增加一个名为 hadoop 的用户。
首先按 ctrl+alt+t 打开终端窗口,输入如下命令创建新用户 :
sudo useradd -m hadoop -s /bin/bash
这条命令创建了可以登陆的 hadoop 用户,并使用 /bin/bash 作为 shell。
sudo passwd hadoop
sudo adduser hadoop sudo
最后注销当前用户(点击屏幕右上角的齿轮,选择注销),返回登陆界面。在登陆界面中选择刚创建的 hadoop 用户进行登陆。
2、更新apt
用 hadoop 用户登录后,需先更新一下 apt,后续我们使用 apt 安装软件,如果没更新可能有一些软件安装不了。进入终端窗口,执行如下命令:
sudo apt-get update
若出现更新不了的情况,请前往”系统设置——软件和更新——下载自”选择https://mirrors.aliyun.com/ubuntu,将更新源更改完成后重新尝试输入上述命令
后续需要更改一些配置文件,在此安装一下 vim(vi增强版,基本用法相同),命令如下;安装时若需要确认,在提示处输入 y 即可。
sudo apt-get install vim
3、安装SSH、配置SSH无密码登陆
集群、单节点模式都需要用到 SSH 登陆(类似于远程登陆,你可以登录某台 Linux 主机,并且在上面运行命令),Ubuntu 默认已安装了 SSH client,此外还需要安装 SSH server:
sudo apt-get install openssh-server
安装后,可以使用如下命令登陆本机:
ssh localhost
此时会有如下提示(SSH首次登陆提示),输入 yes 。然后按提示输入密码 hadoop,这样就登陆到本机了。
但这样登陆是需要每次输入密码的,我们需要配置成SSH无密码登陆比较方便。
首先退出刚才的 ssh,就回到了我们原先的终端窗口,然后利用 ssh-keygen 生成密钥,并将密钥加入到授权中:
exit # 退出刚才的 ssh localhost
cd ~/.ssh/ # 若没有该目录,请先执行一次ssh localhost
ssh-keygen -t rsa # 会有提示,都按回车就可以
cat ./id_rsa.pub >> ./authorized_keys # 加入授权
此时再用 ssh localhost 命令,无需输入密码就可以直接登陆了,如下图所示。
1、安装JDK
Hadoop3.1.3需要JDK版本在1.8及以上。下面演示手动安装JDK1.8。
JDK1.8的安装包jdk-8u162-linux-x64.tar.gz已放在百度云盘,链接: 可以点击这里到百度云盘下载JDK1.8安装包.(提取码:99bg)。请把压缩格式的文件jdk-8u162-linux-x64.tar.gz下载,假设保存在“/home/linziyu/Downloads/”目录下。
接下里在Linux命令行界面中执行如下命令(注意:当前登录用户名是hadoop):
cd /usr/lib
sudo mkdir jvm #创建/usr/lib/jvm目录用来存放JDK文件
cd ~ #进入hadoop用户的主目录
cd Downloads #注意区分大小写字母,刚才已经通过FTP软件把JDK安装包jdk-8u162-linux-x64.tar.gz上传到该目录下
sudo tar -zxvf ./jdk-8u162-linux-x64.tar.gz -C /usr/lib/jvm #把JDK文件解压到/usr/lib/jvm目录下
JDK文件解压缩以后,执行如下命令到/usr/lib/jvm目录查看一下。看到在/usr/lib/jvm目录下有个jdk1.8.0_162目录即安装成功。
cd /usr/lib/jvm
ls
cd ~
vim ~/.bashrc
通过vim编辑器。打开环境变量配置.bashrc文件,在文件开头添加如下几行内容:
export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_162
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
保存.bashrc文件并退出vim编辑器。然后继续执行命令让.bashrc文件的配置立即生效:
source ~/.bashrc
继续验证安装情况:
java -version
Hadoop的安装方式有三种,分别是单机模式,伪分布式模式,分布式模式。在此选择伪分布模式:Hadoop在单节点上以伪分布式的方式运行,Hadoop 进程以分离的 Java 进程来运行,节点既作为 NameNode 也作为 DataNode,同时读取的也是 HDFS 中的文件。可到Hadoop官网下载hadoop-2.10.0.tar.gz 或从网盘中下载: 点击下载.(提取码:99bg)
1、安装Hadoop
我们选择将 Hadoop 安装至 /usr/local/ 中:
sudo tar -zxf ~/下载/hadoop-2.6.0.tar.gz -C /usr/local # 解压到/usr/local中
cd /usr/local/
sudo mv ./hadoop-2.6.0/ ./hadoop # 将文件夹名改为hadoop
sudo chown -R hadoop ./hadoop # 修改文件权限
Hadoop 解压后即可使用。输入如下命令来检查 Hadoop 是否可用,成功则会显示 Hadoop 版本信息:
cd /usr/local/hadoop
./bin/hadoop version
2、对Hadoop进行伪分布式的配置(Hadoop默认安装好单机配置)
Hadoop 的配置文件位于 /usr/local/hadoop/etc/hadoop/ 中,伪分布式需要修改2个配置文件 core-site.xml 和 hdfs-site.xml 。Hadoop的配置文件是 xml 格式,每个配置以声明 property 的 name 和 value 的方式来实现。
cd /usr/local/hadoop/etc/hadoop/
在进行修改配置文件前,需要创建相应的文件夹进行存放,以防后续操作无法启动Hadoop
sudo mkdir /usr/local/hadoop/tmp
sudo mkdir /usr/local/hadoop/tmp/dfs/name
sudo mkdir /usr/local/hadoop/tmp/dfs/data
下面开始配置core-site.xml 和 hdfs-site.xml
vim core-site.xml
在配置文件中找到下面这个标签对
</configuration>
修改为下面配置:
hadoop.tmp.dir</name>
file:/usr/local/hadoop/tmp</value>
Abase for other temporary directories.</description>
</property>
fs.defaultFS</name>
hdfs://localhost:9000</value>
</property>
</configuration>
同样的,修改配置文件 hdfs-site.xml:
dfs.replication</name>
1</value>
</property>
dfs.namenode.name.dir</name>
file:/usr/local/hadoop/tmp/dfs/name</value>
</property>
dfs.datanode.data.dir</name>
file:/usr/local/hadoop/tmp/dfs/data</value>
</property>
</configuration>
3、格式化NameNode
配置完成后,执行 NameNode 的格式化:成功的话,会看到 “successfully formatted” 和 “Exitting with status 0” 的提示。
cd /usr/local/hadoop
./bin/hdfs namenode -format
cd /usr/local/hadoop
./sbin/start-dfs.sh #start-dfs.sh是个完整的可执行文件,中间没有空格
若出现如下SSH提示,输入yes即可。
启动时可能会出现如下 WARN 提示:WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform… using builtin-java classes where applicable WARN 提示可以忽略,并不会影响正常使用
5、验证安装是否成功
启动完成后,可以通过命令 jps 来判断是否成功启动,若成功启动则会列出如下进程: “NameNode”、”DataNode” 和 “SecondaryNameNode”
成功启动后,可以访问 Web 界面 http://localhost:50070 查看 NameNode 和 Datanode 信息,还可以在线查看 HDFS 中的文件。
1、上传文件
准备一个待分析的英语文本文件,在此我选择30000多字的《哈姆雷特》原文剧本,需要可:点击下载.
将hamlet.txt文件放置于/usr/local/hadoop目录下中,以便后续操作
接下来将实验文件上传到HDFS中(Hadoop已为开启状态)
./bin/hdfs dfs -put /usr/local/hadoop/demo.txt input
接着使用 ls 命令查看文件上传情况,上传成功后可以在文件中看到文件
./bin/hdfs dfs –ls input
2、在Ubuntu中安装Eclipse
Hadoop不同的文件系统之间通过调用Java API进行交互,利用Java API进行交互,需要利用软件Eclipse编写Java程序。
利用Ubuntu左侧边栏自带的软件中心安装软件,在Ubuntu左侧边栏打开软件中心搜索下载。
3、配置 Hadoop-Eclipse-Plugin
Hadoop-Eclipse-Plugin可从这里 点击下载。下载后,将 release 中的 hadoop-eclipse-kepler-plugin-2.6.0.jar 复制到 Eclipse 安装目录的 plugins 文件夹中,运行 eclipse -clean 重启 Eclipse 即可(添加插件后只需要运行一次该命令,以后按照正常方式启动就行了)。命令如下:
unzip -qo ~/下载/hadoop2x-eclipse-plugin-master.zip -d ~/下载 # 解压到~/下载中
sudo cp ~/下载/hadoop2x-eclipse-plugin-master/release/hadoop-eclipse-plugin-2.6.0.jar /usr/lib/eclipse/plugins/ # 复制到eclipse安装目录的plugins目录下
/usr/lib/eclipse/eclipse -clean # 添加插件后需要用这种方式使插件生效
执行完以上命令后,系统会自动打开Eclipse,打开后看到左边的Project Explorer里出现了DFS Locations
接下来插件需要进一步的配置,在上方找到Window——Preference
在窗体的左侧找到 Hadoop Map/Reduce 选项,填入Hadoop 的安装地址/usr/local/hadoop
然后切换 Map/Reduce 开发视图,选择 Window 菜单下选择 Open Perspective -> Other,选择 Map/Reduce 选项即可进行切换。
随后可建立与 Hadoop 集群的连接,点击 Eclipse右下角的 Map/Reduce Locations 面板,在面板中单击右键,选择 New Hadoop Location。
在弹出来面板中,General 中的配置参数要与 Hadoop 的配置一致。由于使用的Hadoop伪分布式配置,设置 fs.defaultFS 为 hdfs://localhost:9000,所以此处DFS Master 的 Port 要改为 9000。其余默认即可。
配置好后,点击展开左侧的Project Explorer中能够找到我们上传的文件。
4、创建MapReduce项目
eclipse右上角点击File菜单,选择New——Project
选择Map/Reduce Project,点击Next进入下一步
输入项目名称,点击Finish完成创建
点击展开刚创建的Word Reduce项目,选中右键src 选择NEW – Class 创建java类。
在弹出的窗口中只需填入Package和Name。 Package 处需填写 org.apache.hadoop.examples;Name可自定义;其他默认即可。
5、调用MapReduce对文件中各个单词出现次数进行统计
完成Class创建能看到WordCount.java 这个人间,将下面代码复制进刚创建好的WordCount.java文件中
package org.apache.hadoop.examples;
import java.io.IOException;
import java.util.Iterator;
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 WordCount() {
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
//String[] otherArgs = (new GenericOptionsParser(conf, args)).getRemainingArgs();
String[] otherArgs=new String[]{
"input","output"};
if(otherArgs.length < 2) {
System.err.println("Usage: wordcount [...] " );
System.exit(2);
}
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(WordCount.TokenizerMapper.class);
job.setCombinerClass(WordCount.IntSumReducer.class);
job.setReducerClass(WordCount.IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
for(int i = 0; i < otherArgs.length - 1; ++i) {
FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
}
FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length - 1]));
System.exit(job.waitForCompletion(true)?0:1);
}
public static class IntSumReducer extends Reducer, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
public IntSumReducer() {
}
public void reduce(Text key, Iterable values, Reducer, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
int sum = 0;
IntWritable val;
for(Iterator i$ = values.iterator(); i$.hasNext(); sum += val.get()) {
val = i$.next();
}
this.result.set(sum);
context.write(key, this.result);
}
}
public static class TokenizerMapper extends Mapper
在运行 MapReduce 程序前,需要将 /usr/local/hadoop/etc/hadoop 中将有修改过的配置文件(如伪分布式需要 core-site.xml 和 hdfs-site.xml),以及 log4j.properties 复制到 WordCount 项目下的 src 文件夹(~/workspace/WordCount/src)中,在终端中输入下列几行内容:
cp /usr/local/hadoop/etc/hadoop/core-site.xml ~/workspace/WordCount/src
cp /usr/local/hadoop/etc/hadoop/hdfs-site.xml ~/workspace/WordCount/src
cp /usr/local/hadoop/etc/hadoop/log4j.properties ~/workspace/WordCount/src
复制完成后,务必右键点击 WordCount 选择 refresh 进行刷新,可看到src中多出了几个文件:
完成以上的准备后,点击上面运行按钮,点击Run As——Run on Hadoop启动MapReduce程序
此时可能会提示 “Usage: wordcount “,由于没有指定参数,需要通过Eclipse配置运行参数。
在此点击运行 WordCount.java,此次选择 Run As -> Run Configurations,在此处可以设置运行时的相关参数。选择 “Arguments” 栏,在 Program arguments 处填写 “input output” ;在点击 Run 执行。
当程序执行完毕后,选中图片中的Hadoop文件,右键点击Refresh才能看到输出文件。
Refresh刷新完后,能看到Hadoop目录下生成output文件夹,其中part-r-00000中为各个单词出现次数进行统计的结果。
除了在eclipse中查看结果外,也可以通过命令行查看
cd /usr/local/haddop
./bin/hdfs dfs -cat output/part-r-00000
也可输入下面命令,把HDFS中文件下载到本地文件系统中的“/home/hadoop/下载/”这个目录下
./bin/hdfs dfs -get output/part-r-00000 /home/hadoop/下载
END
[1] http://dblab.xmu.edu.cn/blog/290-2/.
[2] http://dblab.xmu.edu.cn/blog/hadoop-build-project-using-eclipse/.
[3] http://www.cnblogs.com/xia520pi/archive/2012/05/20/2510723.html.
[4] http://www.blogjava.net/LittleRain/archive/2006/12/31/91165.html.