这条路走的很曲折,但让我喜欢上了一句话,“故事的结局很美好,如果不美好,那肯定是还没有结局”。
问题来源:
初学hadoop,在运行MapReduce时,需要先打包生成jar包,再上传jar包到集群,最后执行jar包。刚开始没觉得有何不妥,但多次操作后,发现上传jar包、执行jar包还是有点麻烦。恰好看到老师可以直接在eclipse上执行mapreduce,便冒出了在idea上执行的冲动。
1.首先是我的resources目录,resource目录的结构决定了你是运行在本地还是集群。
2.当我生成jar包,在集群上成功运行时,我知道我的代码没问题。于是我删除hdfs上的目录,在idea上执行main函数。
报出了第一个错:
这是个RpcNoSuchMethodException:即Rpc不存在该方法异常。考虑到Rpc的通信机制是通过相同的函数名来调用,这个异常也就意味着我idea上的hadoop上有setErasureCodingPolicy这个方法,而集群上的hadoop却没这个方法,于是我看了我idea上hadoop的版本是3.0.0,而集群的hadoop是2.5.0.这估计就是原因,我改了idea的hadoop版本为2.5.0这个问题解决了。
2.继续执行main函数,结果遇到了第二个错误。这是个Permission denied,权限拒绝,执行的用户是jyj,而不是用户root。事实上我的hadoop所有操作都是root用户在执行。问题是这里怎么变成了‘jyj’用户?想必是哪里应该设置为root用户而我没设置,而设置肯定既可以在xml中设置也可以在代码中设置。经过百度的不懈搜寻,我找到了解决的一个办法,至于另外一个办法,我知道存在,但不知道在哪里。
于是我在main函数里面指定了执行的用户为root
System.setProperty("HADOOP_USER_NAME", "root");
3.继续执行main函数,好巧遇到了第三个错误。Could not locate executable null\bin\winutils.exe in the Hadoop binaries
这个错误呀,搜过之后才知道老掉牙了,不过是解决linux和window跨平台的一个winutils执行文件没有,于是下载,按照别人的介绍进行操作,什么配置环境变量啊,重启电脑啊,,等等。
不过现在回头看,根本没必要这么做。
4.继续执行main函数,不出所料遇到了第四个错误。因为我知道,问题还多着呢。但没想到这个问题竟这么难缠。
Job job_1528955449633_0014 failed with state FAILED due to: Application application_1528955449633_0014 failed 2 times due to AM Container for appattempt_1528955449633_0014_000002 exited with exitCode: 1 due to: Exception from container-launch: ExitCodeException exitCode=1: /bin/bash: line 0: fg: no job control
ExitCodeException exitCode=1: /bin/bash: line 0: fg: no job control
''no job control'',这个问题字面上是那么好懂,但真的难缠。
百度上提供了一种方式,而且出现了好多次,就是在yarn-site.xml配置属性:如下
<property>
<name>yarn.application.classpath</name>
<value>
/opt/hadoop-2.6.0/etc/hadoop,
/opt/hadoop-2.6.0/share/hadoop/common/*,
/opt/hadoop-2.6.0/share/hadoop/common/lib/*,
/opt/hadoop-2.6.0/share/hadoop/hdfs/*,
/opt/hadoop-2.6.0/share/hadoop/hdfs/lib/*,
/opt/hadoop-2.6.0/share/hadoop/mapreduce/*,
/opt/hadoop-2.6.0/share/hadoop/mapreduce/lib/*,
/opt/hadoop-2.6.0/share/hadoop/yarn/*,
/opt/hadoop-2.6.0/share/hadoop/yarn/lib/*
</value>
</property>
我以为这下好了,运行后,依然报那个错误。
怎么办?到底是哪里原因?是我的hadoop版本太低了,不行吗?于是乎,我装了hadoop2.7.6.当然那些配置文件一个一个改起来,真是烦的无可奈何,稍不留神不是少改就是写错。经过nanenode format,来来回回启动多次hadoop,终于装好了2.7.6.
于是乎,再次执行main函数,心中期盼着这次能成功,但是。。。。。依然不行。
我检查百度提供的方法,怀疑我是不是复制错了,看了一遍又一遍,没错的呀。
无可奈何花落去,难道就要止步这里了吗?
再百度百度吧,实在不行就每次都执行jar包,也还是能接受的。或许以后就知道怎么解决了。我内心已经这么决定了。
又搜索了几次后,终于一个方法让我眼前一亮。
在yarn-site.xml里面添加:
<property>
<name>mapreduce.app-submission.cross-platform</name>
<value>true</value>
</property>
因为我知道"no job control"肯定是与yarn有关,因为yarn是来控制job的。而yarn的配置就是在yarn-site.xml里面。再看一下name,cross-platfrom跨平台的意思,这不就意味着windows和linux这两个平台吗?我所有的问题不就是因为平台不同导致的吗?
终于呀,终于找到了。
我把idea和集群上的yarn-site.xml都做了相应的修改。
这个问题是classNotFoundException,找不到定义的mapper类。这不逗我的吗,明明有这个类,不然我集群执行jar包怎么不报错?思前想后以及百度,让我确定需要在代码中添加jar包,也即要调用
job.setJar()
方法,问题是String类型的参数填什么?我尝试填类名、填jar包名。但一运行就报错,说找不到相应jar包。你不是找不到jar包吗?那我干脆直接把jar包的完全路径写上去。这下总能找到了吧。
历经千辛万苦,终于成功的执行了一次。
喜悦之情,难于言表。
6、回过头来,我看了看设置跨平台这个属性,既然hadoop带有这个属性,那我还需要在windows环境变量中配置winutils吗?我把winutils的路径改了,不用winutils,结果还是顺利执行了。
7、与同学的商讨打开了好多思路,也让我意识到,idea运行的mapreduce是既可以在集群上执行,也可以直接在本地的hadoop执行。就看resources的目录配置了。老师eclipse运行的mapreduce,是在本地运行还是在集群上运行,这曾让我疑惑很久的问题,豁然开朗。
路上很艰难,但若不艰难,怎么能感受到结局的美好呀。