Spark调优老生常谈,范围很广,笔者作为一名Java后端开发兼职Spark-Java开发,此次浅聊一二:Spark OOM如何调优【资源层面】、Spark 业务日志如何完整收集

一. Spark OOM调优

Spark开发的语言无论是基于Java还是Scala,内存管理策略都采用了基于JVM的内存管理来实现。既然基于JVM,那就不可避免面临使用JVM的问题,这里讲讲常见的OOM问题[Java8].

出现下面的情况时,一旦业务处理数据量持续增长,你就要关注了:

记录一次spark oom问题排查 spark oom原因_spark


 

场景一:Heap内存溢出

Spark执行内存#JVM-Heap OOM是常见的问题,那堆既然OOM了是不是调高堆大小就解决问题了呢?在原生Java应用中是可行的(当然前提指的是仅仅的内存不够问题而不是内存持续泄漏和死循环等的问题),然而在Spark中答案是NO的!

  • 当executor内存分配比较小时,即Storage Memory的使用比例较高,此时出现频繁的GC甚至OOM时,因spark-jvm-heap-memeory = spark.executor.memory,故可以调整 spark.executor.memory 进行allocate;
  • 基于第一点,如果allocate后还是频繁GC或OOM,假设你的集群机器#单机内存已经不允许你再继续分配更多的内存给executor时,此时你得用时间换空间了。看看你的executor-cores配置了多少,在spark3中默认的4个core,意味着一个executor可以有4个Task并行处理任务。通过 spark.executor.cores调低可并行的Task,让更少的Task共享更多的JVM内存,也意味着在资源有限的情况下损失了时间换空间,任务Finish的时间要延长
场景二:MetaSpace内存溢出

Spark非执行内存#MetaSpace OOM时,可能是Heap没内存了频繁的Full GC引起,也可能是元空间本身不足以容纳的问题:

  • 如果是Heap Full GC引起的OOM问题,调整方式参考上面的即可;
  • 如果不是Heap Ful GC引起的,那就通过 spark.executor.extraJavaOptions 调整MetaSpace的大小即可,如:spark.executor.extraJavaOptions = -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m。这里要注意Java的版本,Java7是永久代而没有元空间的概念,除了配置参数不一致外,Java8元空间的内存不受JVM内存的限制,内存上限是本地的内存大小

大部分情况下,通过资源的调整就可以解决大部分问题,不能解决的要通过其他的调整,比如:Shuffle并发粒度、协调开辟堆外内存、内存和分区的倾斜调整等措施

 

二. Spark 业务日志完整收集

业务日志是定位问题不可或缺的存在,那不就收集就好了?

  • Spark在执行任务的过程中,日志的输出量非常的多;
  • 非业层面的ERROR日志,比如Node RPC失败,Task失败等日志也未必会影响到任务的成功执行;
  • 如果不管三七二十八全部收集,要考虑什么问题?ELK采集后对ES的空间存储占用问题;ELK采集的速度能否跟上Yarn-Spark日志聚合上传到DFS后删除本地日志文件的问题,如果不能,那么业务日志采集就会遗漏;关闭日志聚合?【不可能】

所以必要的情况下可以将业务日志通过另外的途径采集到ES中,避免日志遗漏,无关日志影响问题排查,比如通过消息中间件异步消费下来。