省级政务中心IT统计管理实时计算资源,以共享Flink集群的方式提供给分管的下属地市。上线接近一年之久,客户反馈通过yarn-session模式启动的Flink集群JobManager出现故障:基于webui上传jar方式执行任务失败,堆栈提示内存溢出的异常(java.lang.OutOfMemoryError: Compressed class space)。本文从故障异常入手,基于JDK内存模型、排查JDK内存参数解决内存溢出的问题,最后总结常用的排查工具集,详见正文。笔者文章只发布微信公众号:大数据从业者
完整异常日志如下:
Bad Request: "{"errors":["org.apache.flink.runtime.rest.handler.RestHandlerException: Could not execute application.
at org.apache.flink.runtime.webmonitor.handlers.JarRunHandler.lambda$handleRequest$1(JarRunHandler.java:110)
at java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:822)
at java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:797)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1595)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.util.concurrent.CompletionException: java.lang.OutOfMemoryError: Compressed class spaceFlink官方文档提供内存相关Troubleshooting,包括Java heap space、Direct buffer memory、Metaspace、Insufficient number of network buffers、Container Memory Exceeded等等。但是并没有上述CCS(Compressed class space)类型,可见这类异常可能并不常见,感兴趣的可以看下:
https://nightlies.apache.org/flink/flink-docs-release-2.0/docs/deployment/memory/mem_trouble/客户尝试通过设置JDK参数-XX:CompressedClassSpaceSize增加相应内存,但是没有任何改善。通过实践示例操作检查确认如下:
启动yarn-session集群
./yarn-session.sh -Denv.java.opts.jobmanager="-XX:CompressedClassSpaceSize=512M" -d查看JobManager进程JVM参数
jinfo <pid>从上图可以看到,Command line设置的参数值512M,实际并没有生效,还是默认的248M(260046848)。为什么设置不生效呢?这里参考看下JDK经典的内存模型结构图:
虽然说-XX:CompressedClassSpaceSize参数没问题,但是JVM开启指针压缩时(见上面jinfo结果图可以看到默认开启-XX:+UseCompressedOops),CompressedClassSpace内存属于MaxMetaspaceSize子集,即MaxMetaspaceSize=Compressed Class Space Size + Metaspace area (excluding the Compressed Class Space) Size。而默认的MaxMetaspaceSize为256M(见上面jinfo结果图-XX:MaxMetaspaceSize=268435456)。
那么,问题就清晰了,-XX:CompressedClassSpaceSize设置值不能超过-XX:MaxMetaspaceSize设置值。
根据上述jinfo结果图,MaxMetaspaceSize=256M,默认动态分配给CompressedClassSpaceSize=248M。所以,有两种方式配置-XX:CompressedClassSpaceSize:
方法1:只增加MaxMetaspaceSize
./yarn-session.sh -Denv.java.opts.jobmanager="-XX:MaxMetaspaceSize=1G" -d如上图所示,CompressedClassSpaceSize自动动态增加到1016M(1065353216)。
方法2:同时增加MaxMetaspaceSize和CompressedClassSpaceSize
./yarn-session.sh -Denv.java.opts.jobmanager="-XX:MaxMetaspaceSize=1G -XX:CompressedClassSpaceSize=512M" -d如上图所示,CompressedClassSpaceSize已显示增加到512M(536870912)。
注意:从JDK源码来看,CompressedClassSpaceSize设置值限制为1M到3G之间。如图所示:
内存OOM问题调大内存上限只是临时处理手段,还需要持续排查是否存在内存泄漏的隐患。针对本文遇到的Compressed class space内存溢出现象,可以通过如下工具继续排查内存是否泄漏:
通过采集上述指标到Prometheus,可以持续观察类的记载和卸载情况,如图所示:
与方法1 类似,采集JDK MBean参数ClassLoading信息,如图所示:
可以查看当前活跃的ClassLoader及对应的Class总数,如图所示:
可以查看Compressed Class Space最大值、最小值、容量等信息,如图所示:
MC:Metaspace Capacity
CCSMN:Compressed Class Space Minimum
CCSMX:Compressed Class Space Maximum
CCSC:Compressed Class Space Capacity./yarn-session.sh -Denv.java.opts.jobmanager="-XX:+TraceClassLoading -XX:+TraceClassUnloading"通过查看日志文件统计类加载与类卸载情况,如图所示:
使用MAT分析heapdump.hprof文件,Leak Suspects Report初步查看泄露嫌疑。 Dominator Tree 搜索ClassLoader,按Retained Heap排序,关注较大实例:
通过Path to GC Roots检查GC Root引用链
本文从故障异常入手,基于JDK内存模型、排查JDK内存参数解决内存溢出的问题,最后总结常用的排查工具集,详见正文。笔者文章只发布微信公众号:大数据从业者,其他均为转载