红联Linux门户
Linux帮助

Win7中使用Eclipse连接虚拟机中的Ubuntu中的Hadoop2.4

发布时间:2015-04-07 22:31:12来源:linux网站作者:yueritian

一早进入虚拟机启动Hadoop,发生异常,重新格式化一下恢复正常,原因待查(格式化:在hadoop目录下执行bin/hdfs namenode -format)

java.net.ConnectException:Call From chenph-Ubuntu/127.0.1.1 to localhost:9000 failed on connection

试试昨天制作的成果——eclipse插件,按照网上的例子进行配置,失败,现象就是无法连接到虚拟机中的Hadoop,于是试验了如下情况

查看虚拟机中的ip,输入ifconfig,得到192.168.203.136,可以ping通win7的ip192.168.101.120

在win7中无法ping到192.168.203.136,原因是我将虚拟机创建的一个网络适配器禁用了,启用后通过在win7运行ipconfig -all可以看到一个192.168.203.1的ip,这个就是win7和ubuntu俩系统的网段的ip,这样就可以互相ping通了

可是eclipse中还是无法远程连接到hadoop,继续想办法,修改win7中的hosts文件,发现我的hosts文件在系统中没有,后来找到了(没有隐藏,而是设置成了系统保护,去掉保护就行了),增加一条对应的信息192.168.203.136 localhost

在eclipse中还是不行,这时候去ubuntu再次执行ipconfig,ip竟然变成了192.168.203.137,我眼花了?


把配置的ip统一改成192.168.203.137,再次试验,依然不行

这时候我把矛头指向了hadoop的配置,将所有配置localhost的地方统一改成了机器名,重新启动服务后,依然不行

因为ip自己会变的问题(可能是dhcp自动分配的问题吧,回头设置成固定的试试),所以上一步我用的机器名,这次我统一改成了ip

成了,一上午没白忙活
Win7中使用Eclipse连接虚拟机中的Ubuntu中的Hadoop2.4


昨天下午继续eclipse与Hadoop间的开发测试,很不顺利,虚拟机中的ip果然又变了,设置成手动的后虚拟机中的就上不了网了,检查了各种参数也没有办法,上不了就上不了吧,能别老变ip就行了

在win7环境下,使用我eclipse4.3.2加上我前天制作的hadoop2.4的插件进行测试,报异常

Exception in thread "main" java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z

网上有相关的介绍,需要下载hadoop.dll,winutils.exe(下载地址)把这两个文件放到win下你hadoop目录下的bin文件夹中(网上有介绍说直接替换现有bin,我的还是会出现这个问题,可能是版本问题吧,毕竟我用的是2.4,上边这两个文件是属于2.2版本的)

放好后,重新运行程序(我使用的Run Application),还是报上边的错,找到源码,把源码放到我的项目里进行debug,找到第571行,改为直接return true;

再次重新运行程序,成功,上张图
Win7中使用Eclipse连接虚拟机中的Ubuntu中的Hadoop2.4


装好插件后显示的你配置的hdfs的目录,比在Ubuntu中方便一点,可以新增、删除、查看文件

上边提的那个错误,我直接修改的这个类

这个要注意,如果你不放log4j的配置文件,你会错过很多有用的报错信息,我刚开始就是没放这个文件,浪费了至少5,6个小时走弯路

将输入和输出文件路径在文件中定义好,这里需要说的是如果你的输出文件夹已经存在,再次运行的时候会报错的

运行信息,成功后可以在输出文件夹中的相应文件查看结果

调试过程中,几度崩溃,就是因为没有在工程里添加log4j,最后看到曙光是因为在ubuntu中的eclipse调试成功了(这个eclipse插件我用的是网上下载的2.2的插件)

win7下,我没有装cygwin,用的是我自己编译的2.4的eclipse插件,从网上下了那个dll和exe直接放到hadoop的bin目录下,eclipse中的hadoop也是配置的hadoop根目录,网上的资料顶多算参考。


经过前面的学习,基本上可以小试牛刀编写一些小程序玩一玩了,在此之前做几项准备工作

明确我要用Hadoop干什么

大体学习一下mapreduce

Ubuntu重启后,再启动hadoop会报连接异常的问题

答:数据提炼、探索数据、挖掘数据

map=切碎,reduce=合并

重启后会清空tmp文件夹,默认namenode会存在这里,需要在core-site.xml文件中增加(别忘了创建文件夹,没权限的话,需要用root创建并把权限改成777):

<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/tmp</value>
</property>

大数据,我的第一反应是现有关系型数据库中的数据怎么跟hadoop结合使用,网上搜了一些资料,使用的是DBInputFormat,那就简单编写一个从数据库读取数据,然后经过处理后,生成文件的小例子吧

数据库弄的简单一点吧,id是数值整型、test是字符串型,需求很简单,统计TEST字段出现的数量
Win7中使用Eclipse连接虚拟机中的Ubuntu中的Hadoop2.4

注:以上图片上传到红联Linux系统教程频道中。


数据读取类:

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapreduce.lib.db.DBWritable;

public class DBRecoder implements Writable, DBWritable{
String test;
int id;
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(test);
out.writeInt(id);
}
@Override
public void readFields(DataInput in) throws IOException {
test = in.readUTF();
id = in.readInt();
}
@Override
public void readFields(ResultSet arg0) throws SQLException {
test = arg0.getString("test");
id = arg0.getInt("id");
}
@Override
public void write(PreparedStatement arg0) throws SQLException {
arg0.setString(1, test);
arg0.setInt(2, id);
}
}


mapreduce操作类

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
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.db.DBConfiguration;
import org.apache.hadoop.mapreduce.lib.db.DBInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class DataCountTest {
public static class TokenizerMapper extends Mapper<LongWritable, DBRecoder, Text, IntWritable> {
public void map(LongWritable key, DBRecoder value, Context context) throws IOException, InterruptedException {
context.write(new Text(value.test), new IntWritable(1));
}
}
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 {
args = new String[1];
args[0] = "hdfs://192.168.203.137:9000/user/chenph/output1111221";

Configuration conf = new Configuration();
 
DBConfiguration.configureDB(conf, "Oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@192.168.101.179:1521:orcl", "chenph", "chenph");
 
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();

Job job = new Job(conf, "DB count");
job.setJarByClass(DataCountTest.class);
job.setMapperClass(TokenizerMapper.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
String[] fields1 = { "id", "test"};
DBInputFormat.setInput(job, DBRecoder.class, "t1", null, "id",  fields1);
FileOutputFormat.setOutputPath(job, new Path(otherArgs[0]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}


开发过程中遇到的问题:

Job被标记为已作废,那应该用什么我还没有查到
乱码问题,hadoop默认是utf8格式的,如果读取的是gbk的需要进行处理
这类例子网上挺少的,有也是老版的,新版的资料没有,我完全是拼凑出来的,很多地方还不甚了解,需要进一步学习官方资料
搜索资料时,有资料说不建议采用这种方式处理实际的大数据问题,原因就是并发过高,会瞬间秒杀掉数据库,一般都会采用导成文本文件的形式。