hadoop java 调试_eclipse/intellij idea 远程调试hadoop 2.6.0

很多hadoop初学者估计都我一样,由于没有足够的机器资源,只能在虚拟机里弄一个linux安装hadoop的伪分布,然后在host机上win7里使用eclipse或Intellj idea来写代码测试,那么问题来了,win7下的eclipse或intellij idea如何远程提交map/reduce任务到远程hadoop,并断点调试?

一、准备工作

1.1 在win7中,找一个目录,解压hadoop-2.6.0,本文中是D:\yangjm\Code\study\hadoop\hadoop-2.6.0 (以下用$HADOOP_HOME表示)

1.2 在win7中添加几个环境变量

HADOOP_HOME=D:\yangjm\Code\study\hadoop\hadoop-2.6.0

HADOOP_BIN_PATH=%HADOOP_HOME%\bin

HADOOP_PREFIX=D:\yangjm\Code\study\hadoop\hadoop-2.6.0

另外,PATH变量在最后追加;%HADOOP_HOME%\bin

二、eclipse远程调试

1.1 下载hadoop-eclipse-plugin插件

hadoop-eclipse-plugin是一个专门用于eclipse的hadoop插件,可以直接在IDE环境中查看hdfs的目录和文件内容。其源代码托管于github上,官网地址是 https://github.com/winghc/hadoop2x-eclipse-plugin

有兴趣的可以自己下载源码编译,百度一下N多文章,但如果只是使用 https://github.com/winghc/hadoop2x-eclipse-plugin/tree/master/release%20 这里已经提供了各种编译好的版本,直接用就行,将下载后的hadoop-eclipse-plugin-2.6.0.jar复制到eclipse/plugins目录下,然后重启eclipse就完事了

1.2 下载windows64位平台的hadoop2.6插件包(hadoop.dll,winutils.exe)

在hadoop2.6.0源码的hadoop-common-project\hadoop-common\src\main\winutils下,有一个vs.net工程,编译这个工程可以得到这一堆文件,输出的文件中,

hadoop.dll、winutils.exe 这二个最有用,将winutils.exe复制到$HADOOP_HOME\bin目录,将hadoop.dll复制到%windir%\system32目录 (主要是防止插件报各种莫名错误,比如空对象引用啥的)

1.3 配置hadoop-eclipse-plugin插件

启动eclipse,windows->show view->other

8f4ede4abec84c92904b74f72509fe43.png

window->preferences->hadoop map/reduce 指定win7上的hadoop根目录(即:$HADOOP_HOME)

a447c283049004a2e2230f9aa1725938.png

然后在Map/Reduce Locations 面板中,点击小象图标

37ac85fc2df25da0a9b94eb1f32657f8.png

添加一个Location

923c17e15e61eeee8455be0d3c4ac782.png

这个界面灰常重要,解释一下几个参数:

Location name 这里就是起个名字,随便起

Map/Reduce(V2) Master Host 这里就是虚拟机里hadoop master对应的IP地址,下面的端口对应 hdfs-site.xml里dfs.datanode.ipc.address属性所指定的端口

DFS Master Port: 这里的端口,对应core-site.xml里fs.defaultFS所指定的端口

最后的user name要跟虚拟机里运行hadoop的用户名一致,我是用hadoop身份安装运行hadoop 2.6.0的,所以这里填写hadoop,如果你是用root安装的,相应的改成root

这些参数指定好以后,点击Finish,eclipse就知道如何去连接hadoop了,一切顺利的话,在Project Explorer面板中,就能看到hdfs里的目录和文件了

ddbb43eb4d4629031d5a00b08ea9857d.png

可以在文件上右击,选择删除试下,通常第一次是不成功的,会提示一堆东西,大意是权限不足之类,原因是当前的win7登录用户不是虚拟机里hadoop的运行用户,解决办法有很多,比如你可以在win7上新建一个hadoop的管理员用户,然后切换成hadoop登录win7,再使用eclipse开发,但是这样太烦,最简单的办法:

hdfs-site.xml里添加

1

2 dfs.permissions

3 false

4

然后在虚拟机里,运行hadoop dfsadmin -safemode leave

保险起见,再来一个 hadoop fs -chmod 777 /

总而言之,就是彻底把hadoop的安全检测关掉(学习阶段不需要这些,正式生产上时,不要这么干),最后重启hadoop,再到eclipse里,重复刚才的删除文件操作试下,应该可以了。

1.4 创建WoldCount示例项目

新建一个项目,选择Map/Reduce Project

98a701c1bf4aa7fb526a60ddbad86f0b.png

后面的Next就行了,然后放一上WodCount.java,代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageyjmyzz;2

3 importjava.io.IOException;4 importjava.util.StringTokenizer;5

6 importorg.apache.hadoop.conf.Configuration;7 importorg.apache.hadoop.fs.Path;8 importorg.apache.hadoop.io.IntWritable;9 importorg.apache.hadoop.io.Text;10 importorg.apache.hadoop.mapreduce.Job;11 importorg.apache.hadoop.mapreduce.Mapper;12 importorg.apache.hadoop.mapreduce.Reducer;13 importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;14 importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;15 importorg.apache.hadoop.util.GenericOptionsParser;16

17 public classWordCount {18

19 public static classTokenizerMapper20 extends Mapper{21

22 private final static IntWritable one = new IntWritable(1);23 private Text word = newText();24

25 public void map(Object key, Text value, Context context) throwsIOException, InterruptedException {26 StringTokenizer itr = newStringTokenizer(value.toString());27 while(itr.hasMoreTokens()) {28 word.set(itr.nextToken());29 context.write(word, one);30 }31 }32 }33

34 public static class IntSumReducer extends Reducer{35 private IntWritable result = newIntWritable();36

37 public void reduce(Text key, Iterable values, Context context) throwsIOException, InterruptedException {38 int sum = 0;39 for(IntWritable val : values) {40 sum +=val.get();41 }42 result.set(sum);43 context.write(key, result);44 }45 }46

47 public static void main(String[] args) throwsException {48 Configuration conf = newConfiguration();49 String[] otherArgs = newGenericOptionsParser(conf, args).getRemainingArgs();50 if (otherArgs.length < 2) {51 System.err.println("Usage: wordcount [...] ");52 System.exit(2);53 }54 Job job = Job.getInstance(conf, "word count");55 job.setJarByClass(WordCount.class);56 job.setMapperClass(TokenizerMapper.class);57 job.setCombinerClass(IntSumReducer.class);58 job.setReducerClass(IntSumReducer.class);59 job.setOutputKeyClass(Text.class);60 job.setOutputValueClass(IntWritable.class);61 for (int i = 0; i < otherArgs.length - 1; ++i) {62 FileInputFormat.addInputPath(job, newPath(otherArgs[i]));63 }64 FileOutputFormat.setOutputPath(job,65 new Path(otherArgs[otherArgs.length - 1]));66 System.exit(job.waitForCompletion(true) ? 0 : 1);67 }68 }

View Code

然后再放一个log4j.properties,内容如下:(为了方便运行起来后,查看各种输出)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 log4j.rootLogger=INFO,stdout2

3 #log4j.logger.org.springframework=INFO4 #log4j.logger.org.apache.activemq=INFO5 #log4j.logger.org.apache.activemq.spring=WARN6 #log4j.logger.org.apache.activemq.store.journal=INFO7 #log4j.logger.org.activeio.journal=INFO8

9 log4j.appender.stdout=org.apache.log4j.ConsoleAppender10 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout11 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n

View Code

最终的目录结构如下:

da3d1456dc98d9a77e3a2fb7766c86e7.png

然后可以Run了,当然是不会成功的,因为没给WordCount输入参数,参考下图:

1.5 设置运行参数

aa6e824fcab7faf7e80a7e027e07bc7a.png

因为WordCount是输入一个文件用于统计单词字,然后输出到另一个文件夹下,所以给二个参数,参考上图,在Program arguments里,输入

hdfs://172.28.20.xxx:9000/jimmy/input/README.txt

hdfs://172.28.20.xxx:9000/jimmy/output/

大家参考这个改一下(主要是把IP换成自己虚拟机里的IP),注意的是,如果input/READM.txt文件没有,请先手动上传,然后/output/ 必须是不存在的,否则程序运行到最后,发现目标目录存在,也会报错,这个弄完后,可以在适当的位置打个断点,终于可以调试了:

f2645489766f38e203d61e79535711b4.png

三、intellij idea 远程调试hadoop

3.1 创建一个maven的WordCount项目

pom文件如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

5 4.0.0

6

7 yjmyzz

8 mapreduce-helloworld

9 1.0-SNAPSHOT

10

11

12

13 org.apache.hadoop

14 hadoop-common

15 2.6.0

16

17

18 org.apache.hadoop

19 hadoop-mapreduce-client-jobclient

20 2.6.0

21

22

23 commons-cli

24 commons-cli

25 1.2

26

27

28

29

30 ${project.artifactId}

31

32

33

View Code

项目结构如下:

d3bf88bf1b0237bdbd4c067f6df9d5fc.png

项目上右击-》Open Module Settings 或按F12,打开模块属性

5d8a273c00d4418c7d9ffb4dcf862c72.png

添加依赖的Libary引用

7c7b2587c63df60c2a6367a62f13102b.png

然后把$HADOOP_HOME下的对应包全导进来

9ef575a46b09c1563fe41d2aceac2f5f.png

导入的libary可以起个名称,比如hadoop2.6

1bb4382985c8053fcb2bd1d5988b7490.png

3.2 设置运行参数

ea510890d0d251ffd2dc459436f6304d.png

注意二个地方:

1是Program aguments,这里跟eclipes类似的做法,指定输入文件和输出文件夹

2是Working Directory,即工作目录,指定为$HADOOP_HOME所在目录

然后就可以调试了

e5eb58a83432eacd10a75c1c24e4c113.png

intellij下唯一不爽的,由于没有类似eclipse的hadoop插件,每次运行完wordcount,下次再要运行时,只能手动命令行删除output目录,再行调试。为了解决这个问题,可以将WordCount代码改进一下,在运行前先删除output目录,见下面的代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packageyjmyzz;2

3 importjava.io.IOException;4 importjava.util.StringTokenizer;5

6 importorg.apache.hadoop.conf.Configuration;7 importorg.apache.hadoop.fs.FileSystem;8 importorg.apache.hadoop.fs.Path;9 importorg.apache.hadoop.io.IntWritable;10 importorg.apache.hadoop.io.Text;11 importorg.apache.hadoop.mapreduce.Job;12 importorg.apache.hadoop.mapreduce.Mapper;13 importorg.apache.hadoop.mapreduce.Reducer;14 importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;15 importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;16 importorg.apache.hadoop.util.GenericOptionsParser;17

18 public classWordCount {19

20 public static classTokenizerMapper21 extends Mapper{22

23 private final static IntWritable one = new IntWritable(1);24 private Text word = newText();25

26 public void map(Object key, Text value, Context context) throwsIOException, InterruptedException {27 StringTokenizer itr = newStringTokenizer(value.toString());28 while(itr.hasMoreTokens()) {29 word.set(itr.nextToken());30 context.write(word, one);31 }32 }33 }34

35 public static class IntSumReducer extends Reducer{36 private IntWritable result = newIntWritable();37

38 public void reduce(Text key, Iterable values, Context context) throwsIOException, InterruptedException {39 int sum = 0;40 for(IntWritable val : values) {41 sum +=val.get();42 }43 result.set(sum);44 context.write(key, result);45 }46 }47

48

49 /**

50 * 删除指定目录51 *52 *@paramconf53 *@paramdirPath54 *@throwsIOException55 */

56 private static void deleteDir(Configuration conf, String dirPath) throwsIOException {57 FileSystem fs =FileSystem.get(conf);58 Path targetPath = newPath(dirPath);59 if(fs.exists(targetPath)) {60 boolean delResult = fs.delete(targetPath, true);61 if(delResult) {62 System.out.println(targetPath + " has been deleted sucessfullly.");63 } else{64 System.out.println(targetPath + " deletion failed.");65 }66 }67

68 }69

70 public static void main(String[] args) throwsException {71 Configuration conf = newConfiguration();72 String[] otherArgs = newGenericOptionsParser(conf, args).getRemainingArgs();73 if (otherArgs.length < 2) {74 System.err.println("Usage: wordcount [...] ");75 System.exit(2);76 }77

78 //先删除output目录

79 deleteDir(conf, otherArgs[otherArgs.length - 1]);80

81 Job job = Job.getInstance(conf, "word count");82 job.setJarByClass(WordCount.class);83 job.setMapperClass(TokenizerMapper.class);84 job.setCombinerClass(IntSumReducer.class);85 job.setReducerClass(IntSumReducer.class);86 job.setOutputKeyClass(Text.class);87 job.setOutputValueClass(IntWritable.class);88 for (int i = 0; i < otherArgs.length - 1; ++i) {89 FileInputFormat.addInputPath(job, newPath(otherArgs[i]));90 }91 FileOutputFormat.setOutputPath(job,92 new Path(otherArgs[otherArgs.length - 1]));93 System.exit(job.waitForCompletion(true) ? 0 : 1);94 }95 }

View Code

但是光这样还不够,在IDE环境中运行时,IDE需要知道去连哪一个hdfs实例(就好象在db开发中,需要在配置xml中指定DataSource一样的道理),将$HADOOP_HOME\etc\hadoop下的core-site.xml,复制到resouces目录下,类似下面这样:

172f011a83db18a1c918ad2d7febcfcc.png

里面的内容如下:

fs.defaultFS

hdfs://172.28.20.***:9000

上面的IP换成虚拟机里的IP即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值