hadoop常见问题总结

hadoop常见问题总结

正式接触hadoop全家桶已经有一年的时间了,期间也踩了很多坑,
大部分的坑踩完了之后也就过去了...
现在将从接触hadoop开始还有所记录的坑总结一下, 以此自省
1. mapRedue本地执行报错 : could not locate executable winutils.exe in the hadoop binaries

hadoop常见问题总结_第1张图片

分析 : 从报错信息来看,是目录下缺少文件导致的
去报错的路径下查看, 发现该目录下没有这个文件,
于是,去该链接下下载

文件下载链接

找到对应的版本下载完毕之后
把winutis.exe ,hadoop.dll这两个文件拷贝到HADOOP_HOME/bin目录下
再次执行程序,依然报同样的错误  
把这两个文件复制 到C:\Windows\目录下,重新执行,该问题得到了解决

为什么这两个文件不存在会报异常呢?这两个文件的作用又是怎样呢?
windows本地运行mr程序时(不提交到yarn,运行在jvm靠线程执行),
hadoop.dll防止报nativeio异常、winutils.exe没有的话报空指针异常。
2. 集群通信异常

hadoop常见问题总结_第2张图片

从报错信息可以明显的看到 : 是和集群的通信异常所导致的
首先检查 :   ip地址和端口号设置是否有误
确认无误后,检查集群是否启动,该节点是否挂掉
将该节点重新启动即可
3.本地调试强转异常

  本地调试程序时碰到如下问题 :
hadoop常见问题总结_第3张图片

    报错代码 : 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");  
4.创建job对象后conf的修改无效
问题场景 : 
     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的操作才是会生效的
5. hive启动时遇到问题

  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目录下发现了这个文件

hadoop常见问题总结_第4张图片

删掉该文件问题,重启hive,问题得到解决!
6. 几种常见的.gz文件异常导致map失败的问题

hadoop常见问题总结_第5张图片
hadoop常见问题总结_第6张图片
hadoop常见问题总结_第7张图片

像上述这种由压缩文件损坏导致的问题,即使加上完善的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块里面将该有问题的文件删除即可
7. Too Many fetch failures.Failing the attempt

  map阶段全部成功之后, fench阶段疯狂报错,如下所示:
hadoop常见问题总结_第8张图片
  几分钟之后,更骚的出现了,已经完成的吧部分map纷纷回滚!,如下图所示:
hadoop常见问题总结_第9张图片

分析,从结果来看 : 就是之前成功的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;
  }
8. java.io.IOException: No input paths specified in job
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)
没有作业中指定的输入路径 
解决方法 : 检验输入路径是否有误, 检验路径下是否有数据

你可能感兴趣的:(大数据开发)