记一次spark streaming内存泄漏分析

一个spark streaming应用executor所耗内存随着时间的增长一直在增加,直到executor内存不足导致应用异常终止,单从代码层面上还无法定位到内存泄漏的位置。因此可通过监控executor进程内存,获取内存变化情况。这里使用java自带的jmc(java mission control)工具来监控进程。
环境信息:
JDK:1.8
Spark:2.3.2
Windows:win10
Eclipse: Oxygen.1a Release (4.7.1a)
MAT:1.9.2

一 、使用JMC工具监控executor进程

(一)executor和driver添加jvm参数

需要添加的参数如下:
-Dcom.sun.management.jmxremote.port=7091 //开启远程连接的端口
-Dcom.sun.management.jmxremote.authenticate=false //是否开启验证,改为false
-Dcom.sun.management.jmxremote.ssl=false //是否使用ssl加密协议
如果需要参看飞行记录器,还需要添加如下参数:
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
spark配置方式如下几种:

  1. 在配置文件spark-defaults.conf文件中配置
  2. 在spark-submit参数中配置
  3. 在spark-env.sh中配置
  4. 在代码中使用conf.set()方法设置,driver无法通过该方式设置
    其中executor 的配置项为"spark.executor.extraJavaOptions",driver的配置项为"spark.driver.extraJavaOptions"
    比如在spark-defaults.conf中配置
    spark.driver.extraJavaOptions = -Dcom.sun.management.jmxremote.port=7091 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
    spark.executor.extraJavaOptions = -Dcom.sun.management.jmxremote.port=7092 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
    添加后提交spark应用

(二)打开jmc进行监控

  1. windows环境jdk的bin目录下打开jmc.exe程序
  2. 创建新连接
    “文件”-》“连接”-》“创建新连接”-》“下一步”
    “主机”项填写需要监控的executor所在IP
    “端口”项填写 -Dcom.sun.management.jmxremote.port配置的值
    “连接名称”项填写后,点击“下一步”。
    创建JVM连接
    3.选择连接的工具,选中以下所有项点击“完成”。
    选择要连接到spark-executor的工具
    4.查看jmc监控的各项指标
    其中堆内存使用量,CPU使用率,GC暂停时间是常查看的指标
    监控java进程信息
    通过查看面板上“Used Java Heap Memory”项的值一直在增大,判断为内存泄漏了。具体还不知道是哪些类占用的内存越来越多,我们可通过thread dump文件来分析,可借助相关工具进行分析,工具有很多,我们这里采用的是Eclipse的MAT(Memory Analysis Tool)插件。

二、使用MAT工具分析内存泄漏

(一)安装MAT插件

1.安装MAT插件
打开Eclipse,“Help”-》“Eclipse Marketplace”,Find一栏搜索"MAT",安装“Memory Analyzer xxx”,选择安装项时将optional选项也选中,安装完成后重启Eclipse。
2.**MAT插件
“Window”-》“Perspective”-》“Open Perspective”-》“Other…”-》“Memory Analysis”点击open,打开mat插件。

(二)使用MAT工具分析内存泄漏

1.使用jmap命令获取内存泄漏的executor进程的thread dump
jmap -dump:format=b,file=xxx.hprof
其中“pid”为executor对应的进程号
2.使用MAT打开Dump文件
打开Eclipse,“File”-》“Open Heap Dump…”,打开下载的dump文件xxx.hprof,选中“Leak Suspects Report”点击“Finish”,加载Dump文件
打开dump文件
展示出的结果为内存占用统计,可看到其中一个占用比列远远超过其他部分,达612.3MB
在这里插入图片描述
点击饼状图,进入详情
在这里插入图片描述
可看到TaskQueue队列类的一个实例比例超高,点击“See stacktrace”查看堆栈详情,看到时redis相关实例占用较大内存,确定是redis代码侧导致内存泄漏。调整相关代码后内存泄漏恢复。
在这里插入图片描述