正式接触hadoop全家桶已经有一年的时间了,期间也踩了很多坑,
大部分的坑踩完了之后也就过去了...
现在将从接触hadoop开始还有所记录的坑总结一下, 以此自省
分析 : 从报错信息来看,是目录下缺少文件导致的
去报错的路径下查看, 发现该目录下没有这个文件,
于是,去该链接下下载
文件下载链接
找到对应的版本下载完毕之后
把winutis.exe ,hadoop.dll这两个文件拷贝到HADOOP_HOME/bin目录下
再次执行程序,依然报同样的错误
把这两个文件复制 到C:\Windows\目录下,重新执行,该问题得到了解决
为什么这两个文件不存在会报异常呢?这两个文件的作用又是怎样呢?
windows本地运行mr程序时(不提交到yarn,运行在jvm靠线程执行),
hadoop.dll防止报nativeio异常、winutils.exe没有的话报空指针异常。
从报错信息可以明显的看到 : 是和集群的通信异常所导致的
首先检查 : ip地址和端口号设置是否有误
确认无误后,检查集群是否启动,该节点是否挂掉
将该节点重新启动即可
报错代码 : Configuration conf = new Configuration();
DistributedFileSystem hdfs = (DistributedFileSystem) FileSystem.get(conf);
执行后会出现类型转换异常
原因 : DistributedFileSystem和寻找的类是LocalFileSystem,都是FileSystem的子类,
在本地调试的情况下,默认按照本地文件来处理,得到的实例是LocalFileSystem的,而不是DistributedFileSystem,当然会报这个问题
但是在非本地调试的情况下,不会遇到该问题
解决办法: 在本地调试的情况下, 添加一些conf配置如下:
conf.set("fs.defaultFS", "hdfs://192.168.1.31:9000");
问题场景 :
Job job = Job.getInstance(conf);
获得了该job对象后,设置的conf属性全部无效
在官方的api下面有如下注释 :
The Job makes a copy of the Configuration so
that any necessary internal modifications do not reflect on the incoming
parameter.
大意是 : job对象创建了一个configuration的副本,因此任何必要的内部改动都不会反馈给这个传入的configuration对象,
所以在这种情况下,设置的conf属性不会生效
解决办法: 在获取job对象之前完成所有对conf的配置
如果想要在获取到job对象后继续对conf进行设置的话,需要执行:
Configuration conf = job.getConfiguration();
之后对该conf的操作才是会生效的
hive很长一段时间一直能够正常使用,忽然有一天启动的时候报了如下问题:
java.lang.NoSuchMethodError: org.apache.thrift.protocol.TBinaryProtocol$Factory.<init>(ZZJJ)V
at org.apache.hadoop.hive.metastore.HiveMetaStore.startMetaStore(HiveMetaStore.java:5986)
at org.apache.hadoop.hive.metastore.HiveMetaStore.main(HiveMetaStore.java:5915)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.thrift.protocol.TBinaryProtocol$Factory.<init>(ZZJJ)V
at org.apache.hadoop.hive.metastore.HiveMetaStore.startMetaStore(HiveMetaStore.java:5986)
at org.apache.hadoop.hive.metastore.HiveMetaStore.main(HiveMetaStore.java:5915)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
出现NoSuchMthodError首先想到的就是版本冲突
从报错栈来看是thrift版本不兼容,解决办法如下:
1)去hadoop/lib里查看文件libfb303*.jar及libthrift*.jar的版本号是否与hive/lib里的一致,如果不需要可以直接删除hadoop/lib里的thrift库文件
2)上述处理后,仍然报错,可能是你在hadoop里安装了hue库,hue也使用了thrift库,如果hue要求的thrift库版本与hive/lib了的thrift库版本不一致也会出现该问题,最简单的解决办法是删除hadoop/lib里的hui*.jar库文件,或则采用支持与hive使用的thrift相同版本的hue即可
3)上面的原因排除后,还是没有解决问题,就需要进一步查找hadoop全家桶是否还有其他模块采用了不同版本的thrift了。
最终在hbase的lib目录下发现了这个文件
删掉该文件问题,重启hive,问题得到解决!
像上述这种由压缩文件损坏导致的问题,即使加上完善的try,catch机制也无济于事,框架的处理即是如此,一般情况下无需理会
但如果这种出问题的文件比较多的时候,可能会因为失败的map数目过多导致整个job停掉!
这个时候有两种处理方式 :
1. 调整参数 mapred.max.map.failures.percent 来设置允许map失败的比例,默认是0
举例 : conf.set("mapred.max.map.failures.percent", 10); // 设置map失败的比例为10%
2. 找出所有有问题的.gz文件,并将其删除掉
我之前的一个做法是 : 写一个工具类,遍历某个路径下全部的.gz文件,使用io流读取,如果读取出现异常,说明该文件有问题,
在catch块里面将该有问题的文件删除即可
map阶段全部成功之后, fench阶段疯狂报错,如下所示:
几分钟之后,更骚的出现了,已经完成的吧部分map纷纷回滚!,如下图所示:
分析,从结果来看 : 就是之前成功的map挂掉了
这种情况通常有两个原因 : 1. 网络通信有问题,导致reduce阶段取不到数据
2. 这些回滚的map所在的机器挂掉了
为了找到问题,我跑了几次程序, 并着重查看了失败map的情况, 发现几次程序的运行失败的map都来自与同样的几个节点,
而且成功的map都不在这些节点上, 确定是这些节点的问题
而且ping这些节点的时候发现能够ping通, 证明机器没有挂掉
是网络通信出现的问题,导致reduce阶段取不到数据...
影响 : job仍然能成功执行完!但是所花费的时间比正常的时候多了很多!
这个多花费的时间取决于回滚的map数量,比例
以及回滚的时候分配给这些map的资源是否足够
如果运气比较好分配给这些map资源比较多的话, 这些map执行结束之后继续执行reduce过程影响不会很大
但是如果大部分的资源都分配给了reduce... 就会导致重新回滚的map占用大量的时间,严重影响效率!!!!
解决方案 : 1. 如果是自己的集群, 解决这些节点通信的问题即可!
2. 如果集群是其它厂商提供的(比如说我们),就需要想办法把这些节点过滤掉
于是,我在配置里面配置了那几台需要过滤掉的节点的ip,程序执行的时候检测map,reduce分配的ip地址,
如果和配置的ip一样的话,直接抛出异常 throw new InterruptedException();
抛出异常后,该任务将交由其它节点去执行,并且hadoop框架默认失败次数到达后便不再给该节点分配任务
问题得到解决!
以下是在运行时检测Ip地址的代码
public static List<String> getLocalIP2() {
List<String> localIpList = new ArrayList<>();
try {
Enumeration<NetworkInterface> eni = NetworkInterface.getNetworkInterfaces();
while (eni.hasMoreElements()) {
NetworkInterface networkCard = eni.nextElement();
List<InterfaceAddress> ncAddrList = networkCard
.getInterfaceAddresses();
Iterator<InterfaceAddress> ncAddrIterator = ncAddrList.iterator();
String broadcastAddress = null;
String ipv4Address = null;
while (ncAddrIterator.hasNext()) {
InterfaceAddress networkCardAddress = ncAddrIterator.next();
InetAddress address = networkCardAddress.getAddress();
if (address != null && address instanceof Inet4Address && !address.isLoopbackAddress()&&!address.isLinkLocalAddress()) {
String hostAddress = address.getHostAddress();
ipv4Address = hostAddress;
broadcastAddress = networkCardAddress.getBroadcast().getHostAddress();
//有ipv4地址 && 有非0.0.0.0的广播号 才是真实ip
if (ipv4Address != null && !ipv4Address.isEmpty() && !"0.0.0.0".equals(broadcastAddress)) {
localIpList.add(ipv4Address);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return localIpList;
}
18/05/30 13:56:13 INFO mapreduce.JobSubmitter: Cleaning up the staging area /MyCloudera/hadoop/log/hadoop-yarn/staging/hmaster/.staging/job_1526642378550_0435
Exception in thread "main" java.io.IOException: No input paths specified in job
at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus(FileInputFormat.java:239)
at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.getSplits(FileInputFormat.java:387)
at org.apache.hadoop.mapreduce.JobSubmitter.writeNewSplits(JobSubmitter.java:301)
at org.apache.hadoop.mapreduce.JobSubmitter.writeSplits(JobSubmitter.java:318)
at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:196)
at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1290)
at org.apache.hadoop.mapreduce.Job$10.run(Job.java:1287)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
at org.apache.hadoop.mapreduce.Job.submit(Job.java:1287)
at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:1308)
at cn.mastercom.bigdata.mapr.Main.main(Main.java:338)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
没有作业中指定的输入路径
解决方法 : 检验输入路径是否有误, 检验路径下是否有数据