Open bjkonglu opened 6 years ago
在使用Structured Streaming计算网站的pv和uv时,我编写的实时计算应用上线后经常出现OOM异常,导致任务失败进而服务不可用。通过对应用日志的分析,发现是Driver端的JVM的堆发现了OOM异常,如图所示:
那现在我们将应用异常问题变成了处理Driver进程OOM的问题,OOM异常一般有两个情况:
给JVM分配的内存比较少,可以通过JVM参数-Xmx、-Xms来给JVM分配更多的内存;
发生了内存泄露/溢出,此时我们就得分析代码中那部分出现了内存泄露/溢出
在我的示例中,我首先采用增加Driver的内存来解决问题,但是依旧出现了上述问题,所以我排除了第一种情况,转而分析第二种情况。针对第二种情况,我在启动应用是增加了额外的JVM参数,来记录Driver进程GC的详细信息,以及发生OOM时dump出它的堆内存文件:
--conf spark.driver.extraJavaOptions="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp"
--conf spark.executor.extraJavaOptions="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp"
然后采用eclipse的插件MAT工具分析Driver的内存快照文件,分析的结果如下: 通过分析,我发现Driver JVM内存里存在大量的SparkPlanGraphNodeWrapper没有被回收,因此怀疑此处Spark代码发生了内存泄露,并且在Spark官网找到相同类型的issue和相应的PR
根据上述PR进行修改,上线新的应用后Driver端的内存变化图如下:
从图中我们可以发现:修改后Driver的内存已稳定,没有发生内存泄露。
场景
在使用Structured Streaming计算网站的pv和uv时,我编写的实时计算应用上线后经常出现OOM异常,导致任务失败进而服务不可用。通过对应用日志的分析,发现是Driver端的JVM的堆发现了OOM异常,如图所示:
分析
那现在我们将应用异常问题变成了处理Driver进程OOM的问题,OOM异常一般有两个情况:
给JVM分配的内存比较少,可以通过JVM参数-Xmx、-Xms来给JVM分配更多的内存;
发生了内存泄露/溢出,此时我们就得分析代码中那部分出现了内存泄露/溢出
处理
在我的示例中,我首先采用增加Driver的内存来解决问题,但是依旧出现了上述问题,所以我排除了第一种情况,转而分析第二种情况。针对第二种情况,我在启动应用是增加了额外的JVM参数,来记录Driver进程GC的详细信息,以及发生OOM时dump出它的堆内存文件:
--conf spark.driver.extraJavaOptions="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp"
--conf spark.executor.extraJavaOptions="-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp"
然后采用eclipse的插件MAT工具分析Driver的内存快照文件,分析的结果如下: 通过分析,我发现Driver JVM内存里存在大量的SparkPlanGraphNodeWrapper没有被回收,因此怀疑此处Spark代码发生了内存泄露,并且在Spark官网找到相同类型的issue和相应的PR
结果
根据上述PR进行修改,上线新的应用后Driver端的内存变化图如下:
从图中我们可以发现:修改后Driver的内存已稳定,没有发生内存泄露。