zoukankan      html  css  js  c++  java
  • Spark学习笔记(12)---troubleshooting

    troubleShooting

    控制shuffle reduce端缓冲大小以避免OOM

    有的时候,map端的数据量特别大,然后写出的速度特别快。reduce端所有task,拉取的时候,全部达到自己的缓冲的最大极限值,48M,全部填满。这个时候,再加上你的reduce端执行的聚合函数的代码,可能会创建大量的对象。
    然后,内存就撑不住了,就会OOM。reduce端的内存中,就会发生内存溢出的问题。

    这个时候,就应该减少reduce端task缓冲的大小。我宁愿多拉取几次,但是每次同时能够拉取到reduce端每个task的数量,比较少,就不容易发生OOM内存溢出的问题。(比如,可以调节成12M)

    JVM GC导致shuffle文件拉取失败

    这个问题在JVM调优之调节Executor堆外内存与连接等待时长中提到过, 其中只讲了连接等待的时间,这里还可以配置两个参数

    spark.shuffle.io.maxRetries 3
    spark.shuffle.io.retryWait 5s
    

    第一个参数,意思就是说,shuffle文件拉取的时候,如果没有拉取到(拉取失败),最多或重试几次(会重新拉取几次文件),默认是3次。

    第二个参数,意思就是说,每一次重试拉取文件的时间间隔,默认是5s钟。

    Yarn队列资源不足导致Application直接失败

    不同执行时间提交到不同的队列中去等待,可以通过线程池(一个线程池对应一个资源队列)的方法来实现。

    各种序列化导致的报错

    如果日志文件中出现了类似于Serializable、Serialize等等报错的log,那就是出现了序列化报错。
    序列化报错要注意的三个点:

    (1) 你的算子函数里面,如果使用到了外部的自定义类型的变量,那么此时,就要求你的自定义类型,必须是可序列化的。

    final Teacher teacher = new Teacher("leo");
    
    studentsRDD.foreach(new VoidFunction() {
     
    public void call(Row row) throws Exception {
      String teacherName = teacher.getName();
      ....  
    }
    
    });
    
    public class Teacher implements Serializable {
      
    }
    

    (2) 如果要将自定义的类型,作为RDD的元素类型,那么自定义的类型也必须是可以序列化的

    JavaPairRDD<Integer, Teacher> teacherRDD
    JavaPairRDD<Integer, Student> studentRDD
    studentRDD.join(teacherRDD)
    
    public class Teacher implements Serializable {
      
    }
    
    public class Student implements Serializable {
      
    }
    

    (3) 不能在上述两种情况下,去使用一些第三方的,不支持序列化的类型

    Connection conn = 
    
    studentsRDD.foreach(new VoidFunction() {
     
    public void call(Row row) throws Exception {
      conn.....
    }
    
    });
    

    Connection是不支持序列化的

    算子函数返回NULL导致的问题

    在有些算子函数里面,是需要我们有一个返回值的。但是,有时候,我们可能对某些值,就是不想有什么返回值。我们如果直接返回NULL的话,那么可以不幸的告诉大家,是不行的,会报错的。

    • 解决办法
    1. 在返回的时候,返回一些特殊的值,不要返回null,比如“-999”
    2. 在通过算子获取到了一个RDD之后,可以对这个RDD执行filter操作,进行数据过滤。filter内,可以对数据进行判定,如果是-999,那么就返回false,给过滤掉就可以了。
    3. 在filter之后,可以使用coalesce算子压缩一下RDD的partition的数量,让各个partition的数据比较紧凑一些。也能提升一些性能。

    Yarn-cluster模式JVM内存溢出无法执行

    有的时候,运行一些包含了spark sql的spark作业,可能会碰到yarn-client模式下,可以正常提交运行;yarn-cluster模式下,可能是无法提交运行的,会报出JVM的PermGen(永久代)的内存溢出,OOM。
    yarn-client模式下,driver是运行在本地机器上的,spark使用的JVM的PermGen的配置,是本地的spark-class文件(spark客户端是默认有配置的),JVM的永久代的大小是128M,这个是没有问题的;但是呢,在yarn-cluster模式下,driver是运行在yarn集群的某个节点上的,使用的是没有经过配置的默认设置(PermGen永久代大小),82M。
    spark-sql,它的内部是要进行很复杂的SQL的语义解析、语法树的转换等等,特别复杂,在这种复杂的情况下,如果说你的sql本身特别复杂的话,很可能会比较导致性能的消耗,内存的消耗。可能对PermGen永久代的占用会比较大。

    spark-submit脚本中,加入以下配置即可:

    --conf spark.driver.extraJavaOptions="-XX:PermSize=128M -XX:MaxPermSize=256M"
    

    Tips:
    Spark SQL,有大量的or语句。比如where keywords='' or keywords='' or keywords=''
    当达到or语句,有成百上千的时候,此时可能就会出现一个driver端的jvm stack overflow,JVM栈内存溢出的问题。
    因此可以吧sql语句拆分成多条sql语句来执行

    参考资料

    《北风网Spark项目实战》
    github: https://github.com/yangtong123/StudySpark

  • 相关阅读:
    死磕 java线程系列之线程池深入解析——定时任务执行流程
    死磕 java线程系列之线程池深入解析——未来任务执行流程
    死磕 java线程系列之线程池深入解析——普通任务执行流程
    面试 LockSupport.park()会释放锁资源吗?
    死磕 java线程系列之线程池深入解析——生命周期
    死磕 java线程系列之线程的生命周期
    《动手学深度学习》系列笔记—— 1.2 Softmax回归与分类模型
    《动手学深度学习》系列笔记——1.1 线性回归
    【Python学习笔记】2. 高级变量类型
    【Python学习笔记】1. Python基础知识
  • 原文地址:https://www.cnblogs.com/yangtong/p/7158779.html
Copyright © 2011-2022 走看看