hadoop怎样在window上做实验
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hadoop怎样在window上做实验相关的知识,希望对你有一定的参考价值。
具体安装的细节就不说了,网络上的资料多得很。主要介绍一下自己的经验所得。首先介绍一下手头的软硬件资源:NameNode/JobTracker: HP笔记本 i5 2.4GHz 8G 500GB Win7 64位家庭普通版 hadoop 1.1.2 JDK7u21
DataNode/TaskTracker: HP台式机 i3 3.3GHz 4G 500GB Win7 32位专业版 hadoop 1.1.2 JDK7u21
DataNode/TaskTracker: 联想ThinkPad i5 2.5GHz 4G 500GB Win7 64位家庭普通版 hadoop 1.1.2 JDK7u21
首先,安装CygWin(在官网上下的最新版),一定要选上openssh和openssl的包(缺省是不安装的)。 CygWin在各个计算机上的安装目录可以不同。要把CygWin安装目录下的bin目录、usr/bin目录、usr/sbin目录放到系统环境变量Path中。因为,hadoop会执行一些Linux/UNIX形式的命令如bash、whoami等,而这些命令在CygWin中是以Windows系统中的可执行文件形式存放在前面说的目录中。
CygWin装好之后,以管理员的身份运行Cygwin Terminal,执行ssh-host-config配置SSHD服务。CygWin会在Windows系统中新建一个管理员帐号cyg_server(可以按自己换别的),这个帐号就用来跑hadoop的程序了。过程中有好多地方问yes还是no,我试过全部选yes也试过个别选no(按照网上的资料),结果没发现有什么差别。ssh-host-config执行成功后,SSHD会作为一个系统服务在后台运行,每次系统启动都自动开启。这时,要注意检查或配置Windows的防火墙配置,要放开到SSHD服务的入站连接,我的做法是放开到Cygwin安装目录/usr/sbin/sshd的入站连接。
Cygwin Terminal下执行mkpasswd -l > /etc/passwd和mkgroup -l > /etc/group,主要用途是将Windows的帐号和组别同步到CygWin下。
Windows系统中切换到cyg_server用户(这个帐号的描述缺省是Privileged server),运行Cygwin Terminal,执行ssh-keygen,一直敲回车就行。用ls -a可以看到有一个.ssh的目录,把里面的id_rsa,pub导入到authorized_keys,然后把NameNode上的这个authorized_keys文件,拷贝到所有DataNode和TaskTracker的相同位置下,即 cyg_server用户主目录下的.ssh目录。这样cyg_server用户就可以不需要密码就可以远程登录各个计算机和执行命令。
Hadoop是用java开发的,因此,系统中要有java的运行环境,可以从Oracle的官网下最新的JDK安装,注意是JDK,不是JRE(因为需要用到bin目录下的server目录)。安装的位置必须全部计算机都一样(因为碰到过在DataNode上找不到java程序的情况),那也就是在C:\下面了,给安装目录起一个简短的名称(不要带空格)。在系统环境变量Path中,将JDK安装目录下的bin目录所在路径添加进去。跟SSHD一样,要修改Windows防火墙的入站规则,放开到JDK的java程序网络连接。
到这里,Hadoop主要的运行条件基本具备了,可以安装Hadoop了。过程很简单,从hadoop.apache.org下载一个hadoop的tar.gz包(我下的是1.1.2版本),解压到一个目录下就可以了。这里要注意的是,最好全部操作都在Windows的cyg_server帐号下执行,而且,hadoop解压后存放的目录要所有计算机都一样,例如都放在C:\hadoop-1.1.2目录下。
Hadoop是用java开发的,虽然java号称支持跨平台运行。但是,基于Linux的Hadoop移到Windows平台上时,依然出现严重水土不服,即使是在Cygwin的环境下也一样。同样一段java代码,在Linux下的表现和在Windows下的表现会不一样,导致Windows下运行的Hadoop经常出现异常而终止运行。
实验中大部分的时间都是用来探究引起水土不服的原因,把它消除掉。 下面介绍一下我对这些问题采取的一些解决办法。
众所周知,文件路径在Linux下和在Windows下的解析是不一样的。在Cygwin中运行Windows版本的java时,两种不同形式的文件路径一起出现会导致程序异常。Cygwin下对C:\hadoop-1.1.2的解析是/cygdrive/c/hadoop-1.1.2,而Windows版本的java对'/cygdrive/c/hadoop-1.1.2'的解析又变成C:\cygdrive\c\hadoop-1.1.2,由于这是一个不存在的文件路径,所以Hadoop经常抛出异常说文件找不到,或者自己直接把这个路径创建了(例如,DataNode存放HDFS文件块时寻找dfs.data.dir时)。要解决这个问题,可以利用Windows7的文件链接的特性(类似于linux的链接ln -s),在C:\下创建cygdrive目录,在这个目录里执行MKLINK /D c C:\创建一个到目的目录的目录链接。这样当java访问C:\cygdrive\c\hadoop-1.1.2时就会如我们所愿访问到C:\hadoop-1.1.2这个目录。
能不能用ln -s命令来建这样的链接呢?答案是不行的。Hadoop的源代码中就使用了这样的方法,可是Windows的java不能识别,因此,TaskTracker就不能执行JobTracker分配给它的Task任务。对于这样的情况,除了修改Hadoop代码,好像还没别的办法。要修改的是org.apache.hadoop.fs包里的FileUtil.java文件,里面有一个symLink方法,就是用了ln -s的办法来建文件链接,我们要把它改成使用Windows7的方式建立文件链接。原代码如下:
public static int symLink(String target, String linkname) throws IOException
String cmd = "ln -s " + target + " " + linkname;
Process p = Runtime.getRuntime().exec(cmd, null);
int returnVal = -1;
try
returnVal = p.waitFor();
catch(InterruptedException e)
//do nothing as of yet
if (returnVal != 0)
LOG.warn("Command '" + cmd + "' failed " + returnVal +
" with: " + copyStderr(p));
return returnVal;
修改后,变成如下的样子
public static int symLink(String target, String linkname) throws IOException
// String cmd = "ln -s " + target + " " + linkname;
String newTarget;
String newLinkname;
newTarget = new CygPathWinCommand("C:" + target).getResult();
newLinkname = new CygPathWinCommand(linkname).getResult();
String cmd = "CMD /C \"MKLINK /D " + newLinkname + " " + newTarget + "\"";
Process p = Runtime.getRuntime().exec(cmd, null);
int returnVal = -1;
try
returnVal = p.waitFor();
catch(InterruptedException e)
//do nothing as of yet
if (returnVal != 0)
LOG.warn("Command '" + cmd + "' failed " + returnVal +
" with: " + copyStderr(p));
return returnVal;
private static class CygPathWinCommand extends Shell
String[] command;
String result;
CygPathWinCommand(String path) throws IOException
command = new String[]"cygpath", "-d", path;
run();
String getResult() throws IOException
return result;
protected String[] getExecString()
return command;
protected void parseExecResult(BufferedReader lines) throws IOException
String line = lines.readLine();
if (line == null)
throw new IOException("Can't convert '" + command[2] +
" to a cygwin path");
result = line;
红色部分就是改动后的代码。其中CygPathWinCommand是新加的一个类,它是复制原来CygPathCommand类的样子来作的,只不过原来是使用cygpath -u命令,这里使用cygpath -d命令。
Hadoop在创建完链接或者目录后,通常都设置Linux/Unix形式的访问权限。这在Windows系统上是没有作用的事。所以,Hadoop的文件权限设置操作是无效的,所以当Hadoop验证文件权限设置结果时就会抛出异常而终止。我们可以改动代码,不让它终止。Hadoop验证文件权限的操作是通过org.apache.hadoop.fs包里FileUtil.java文件的checkReturnValue方法实现的,原代码如下:
private static void checkReturnValue(boolean rv, File p,
FsPermission permission
) throws IOException
if (!rv)
throw new IOException("Failed to set permissions of path: " + p +
" to " +
String.format("%04o", permission.toShort()));
修改很简单,不让它抛异常就行了
private static void checkReturnValue(boolean rv, File p,
FsPermission permission
) throws IOException
if (!rv)
LOG.info("Failed to set permissions of path: " + p +
" to " +
String.format("%04o", permission.toShort()));
除了文件路径解析和文件权限设置两个方面,Linux下和在Windows下的进程和线程管理也是不一样的。这会导致org.apache.hadoop.mapred包里JvmManager.java文件里的kill方法抛出异常,原代码如下
synchronized void kill() throws IOException, InterruptedException
if (!killed)
TaskController controller = tracker.getTaskController();
// Check inital context before issuing a kill to prevent situations
// where kill is issued before task is launched.
String pidStr = jvmIdToPid.get(jvmId);
if (pidStr != null)
String user = env.conf.getUser();
int pid = Integer.parseInt(pidStr);
// start a thread that will kill the process dead
if (sleeptimeBeforeSigkill > 0)
new DelayedProcessKiller(user, pid, sleeptimeBeforeSigkill,
Signal.KILL).start();
controller.signalTask(user, pid, Signal.TERM);
else
controller.signalTask(user, pid, Signal.KILL);
else
LOG.info(String.format("JVM Not killed %s but just removed", jvmId
.toString()));
killed = true;
在网上找了好久,终于找到一篇老外的文章讲这个问题,改动也比较简单
synchronized void kill() throws IOException, InterruptedException
if (!killed)
TaskController controller = tracker.getTaskController();
// Check inital context before issuing a kill to prevent situations
// where kill is issued before task is launched.
String pidStr = jvmIdToPid.get(jvmId);
if ((pidStr != null) && !(pidStr.isEmpty()))
String user = env.conf.getUser();
int pid = Integer.parseInt(pidStr);
// start a thread that will kill the process dead
if (sleeptimeBeforeSigkill > 0)
new DelayedProcessKiller(user, pid, sleeptimeBeforeSigkill,
Signal.KILL).start();
controller.signalTask(user, pid, Signal.TERM);
else
controller.signalTask(user, pid, Signal.KILL);
else
LOG.info(String.format("JVM Not killed %s but just removed", jvmId.toString()));
killed = true;
在我的实验中,代码的改动到这里,Hadoop基本就可以跑起来了,HDFS和MapReduce应用都可以运行。下面介绍一下怎么编译改动后的代码。我不是java程序员,只会用原始笨拙的办法去调试和编译。Hadoop的源码在src目录下,在我实验中是C:\hadoop-1.1.2\src,里面有好几个子目录,我们要改动的JvmManager.java文件和FileUtil.java文件都在core子目录下。由于Hadoop是在Linux环境中开发的,所以我们编译最好也在Linux环境下(我试过Windows环境,结果不行,技术有限,没法解决)。首先把这些源文件拷到一台Linux,我的做法是直接下个hadoop的tar.gz包,解压到/var/tmp下,源码就在/var/tmp/hadoop-1.1.1/src目录下了。
1)先解压jar包,我们改动的源码最后都编译打包到hadoop-core-1.1.2.jar包里
cd /var/tmp
mkdir newjar
cp /var/tmp/hadoop-1.1.2/hadoop-core-1.1.2.jar /var/tmp/newjar
cd newjar
jar -xvf hadoop-core-1.1.2.jar
rm -f hadoop-core-1.1.2.jar
2)编译改动后的源码
cd /var/tmp/hadoop-1.1.2/src/core
javac -cp /var/tmp/hadoop-1.1.2/lib/commons-logging-1.1.1.jar:/var/tmp/hadoop-1.1.2/hadoop-core-1.1.2.jar org/apache/hadoop/mapred/JvmManager.java
javac -cp /var/tmp/hadoop-1.1.2/lib/commons-logging-1.1.1.jar:/var/tmp/hadoop-1.1.2/hadoop-core-1.1.2.jar org/apache/hadoop/fs/FileUtil.java
3)打jar包
cp org/apache/hadoop/mapred/*.class /var/tmp/newjar/org/apache/hadoop/mapred
cp org/apache/hadoop/fs/*.class /var/tmp/newjar/org/apache/hadoop/fs
cd /var/tmp/newjar
jar cvfm /var/tmp/test.jar META-INF/MANIFEST.MF .
把test.jar拷下来,替换掉所有计算机的hadoop-core-1.1.2.jar就可以了。
好了,所有事情都就绪了,配置好hadoop的各种配置文件后,顺利启动了hadoop的HDFS和MapReduce框架,以下是进行的一些测试
hadoop jar C:/hadoop-1.1.2/hadoop-test-1.1.2.jar TestDFSIO -write -nrFiles 10 -sizeFile 1000 执行成功,但吞吐量不是很理想
hadoop jar C:/hadoop-1.1.2/hadoop-test-1.1.2.jar TestDFSIO -read -nrFiles 10 -sizeFile 1000 执行成功,但吞吐量比前面的测试还差
hadoop jar C:/hadoop-1.1.2/hadoop-examples-1.1.2.jar randomwriter random-data 执行成功,但时间花了两个多小时,处理的数据有20GB多
hadoop jar C:/hadoop-1.1.2/hadoop-examples-1.1.2.jar sort random-data sorted-data 执行成功,但时间也是花了两个多小时,处理的数据有20GB多
hadoop jar C:/hadoop-1.1.2/hadoop-test-1.1.2.jar testmapredsort -sortInput random-data -sortOut sorted-data 执行成功,但时间也是花了两个多小时,,处理的数据还是20GB多但时间好像还更长些
hadoop jar C:/hadoop-1.1.2/hadoop-examples-1.1.2.jar wordcount /user/cyg_server/tbdata_big output 其中tbdata_big是一个3GB多的文本文件,里面有1亿3千万行文本。实验环境给出的性能是7分钟16秒。自己在NameNode上写一个perl脚本做wordcount相同的事情,耗时562秒。这个......Hadoop只快了106秒。是不是数据太少了? 参考技术A 首先,安装CygWin(在官网上下的最新版),一定要选上openssh和openssl的包(缺省是不安装的)。 CygWin在各个计算机上的安装目录可以不同。要把CygWin安装目录下的bin目录、usr/bin目录、usr/sbin目录放到系统环境变量Path中。因为,hadoop会执行一些Linux/UNIX形式的命令如bash、whoami等,而这些命令在CygWin中是以Windows系统中的可执行文件形式存放在前面说的目录中。
CygWin装好之后,以管理员的身份运行Cygwin Terminal,执行ssh-host-config配置SSHD服务。CygWin会在Windows系统中新建一个管理员帐号cyg_server(可以按自己换别的),这个帐号就用来跑hadoop的程序了。过程中有好多地方问yes还是no,我试过全部选yes也试过个别选no(按照网上的资料),结果没发现有什么差别。ssh-host-config执行成功后,SSHD会作为一个系统服务在后台运行,每次系统启动都自动开启。这时,要注意检查或配置Windows的防火墙配置,要放开到SSHD服务的入站连接,我的做法是放开到Cygwin安装目录/usr/sbin/sshd的入站连接。
Cygwin Terminal下执行mkpasswd -l > /etc/passwd和mkgroup -l > /etc/group,主要用途是将Windows的帐号和组别同步到CygWin下。
Windows系统中切换到cyg_server用户(这个帐号的描述缺省是Privileged server),运行Cygwin Terminal,执行ssh-keygen,一直敲回车就行。用ls -a可以看到有一个.ssh的目录,把里面的id_rsa,pub导入到authorized_keys,然后把NameNode上的这个authorized_keys文件,拷贝到所有DataNode和TaskTracker的相同位置下,即 cyg_server用户主目录下的.ssh目录。这样cyg_server用户就可以不需要密码就可以远程登录各个计算机和执行命令。
Hadoop是用java开发的,因此,系统中要有java的运行环境,可以从Oracle的官网下最新的JDK安装,注意是JDK,不是JRE(因为需要用到bin目录下的server目录)。安装的位置必须全部计算机都一样(因为碰到过在DataNode上找不到java程序的情况),那也就是在C:\下面了,给安装目录起一个简短的名称(不要带空格)。在系统环境变量Path中,将JDK安装目录下的bin目录所在路径添加进去。跟SSHD一样,要修改Windows防火墙的入站规则,放开到JDK的java程序网络连接。
到这里,Hadoop主要的运行条件基本具备了,可以安装Hadoop了。过程很简单,从hadoop.apache.org下载一个hadoop的tar.gz包(比如1.1.2版本),解压到一个目录下就可以了。这里要注意的是,最好全部操作都在Windows的cyg_server帐号下执行,而且,hadoop解压后存放的目录要所有计算机都一样,例如都放在C:\hadoop-1.1.2目录下。
Hadoop是用java开发的,虽然java号称支持跨平台运行。但是,基于Linux的Hadoop移到Windows平台上时,依然出现严重水土不服,即使是在Cygwin的环境下也一样。同样一段java代码,在Linux下的表现和在Windows下的表现会不一样,导致Windows下运行的Hadoop经常出现异常而终止运行。
实验中大部分的时间都是用来探究引起水土不服的原因,把它消除掉。 下面介绍一下对这些问题采取的一些解决办法。
众所周知,文件路径在Linux下和在Windows下的解析是不一样的。在Cygwin中运行Windows版本的java时,两种不同形式的文件路径一起出现会导致程序异常。Cygwin下对C:\hadoop-1.1.2的解析是/cygdrive/c/hadoop-1.1.2,而Windows版本的java对'/cygdrive/c/hadoop-1.1.2'的解析又变成C:\cygdrive\c\hadoop-1.1.2,由于这是一个不存在的文件路径,所以Hadoop经常抛出异常说文件找不到,或者自己直接把这个路径创建了(例如,DataNode存放HDFS文件块时寻找dfs.data.dir时)。要解决这个问题,可以利用Windows7的文件链接的特性(类似于linux的链接ln -s),在C:\下创建cygdrive目录,在这个目录里执行MKLINK /D c C:\创建一个到目的目录的目录链接。这样当java访问C:\cygdrive\c\hadoop-1.1.2时就会如我们所愿访问到C:\hadoop-1.1.2这个目录。
怎么在windows上搭建hadoop环境
1、下载安装JDK,以及Eclipse具体看此链接:http://blog.csdn.net/weixuehao/article/details/17715793
2、新建JAVA Project
3、去cloudera网站下载hadoop的CDH3u6版本。将起解压到win7的某个目录
4、选中OperateHDFS,右击,选择“property”,弹出右侧的窗口;
选择“Java Build Path” —— “Libraries” —— Add External Jars
5、到上面的画面后,下面就是选择开发hadoop程序时,用到的一些jar包
将lib文件夹下的所有的jar包,添加进去;将红框内的jar包,安装进去。
6、创建配置文件夹
7、将core-site.xml,hdfs-site.xml,mapred-site.xml放入到此文件夹中。
8、右键->属性 进行如下操作,添加刚刚创建conf文件夹
配置搞定!
写代码的过程中要写入的namenode和jobtracker地址(修改为你自己的)
在你的代码中,加入如下代码就可以了
Configuration conf = new Configuration();
conf.set("fs.default.name","192.1.1.2:9000");
conf.set("mapred.job.tracker","192.1.1.2:9001"); 参考技术A Hadoop三种安装模式:单机模式,伪分布式,真正分布式 一 单机模式standalone 单机模式是Hadoop的默认模式。当首次解压Hadoop的源码包时,Hadoop无法了解硬件安装环境,便保守地选择了最小配置。在这种默认模式下所有3个XML文件均为空。
以上是关于hadoop怎样在window上做实验的主要内容,如果未能解决你的问题,请参考以下文章