0


记一次flink standalone模式下偶现Metaspace OOM的问题

背景

  • 公司的系统中使用了standalone模式的flink,将队列中的数据处理后送入es等存储,同时使用了独立的保活程序维持flink job的运行,当flink job启动失败时,则会一直重试。

问题发现

  • 某日上班后打开flink web-ui后发现无法正常访问,观测后台日志发现存在metaspace OOM的相关错误,使用arthas attach到进程上,用dashboard命令观测metaspace的大小,发现其**使用率几近于100%**;日志报错

技术背景

  • 阅读flink启动job的相关代码可知,在读入用户提交的jar以后,会生成一个独立的classloader来加载用户jar中的class 查看详解,其目的是使job的运行环境相对独立。
  • flink同时也提供了一个配置项来修改这个行为,即 classloader.resolve-order -在这里插入图片描述

问题解决过程

尝试1

  • 猜测: 纯属偶然的现象,调大metaspace的size
  • 执行: 修改flink-conf.yaml 中的jobmanager.memory.jvm-metaspace.size 属性 设置为340M
  • 结果: 无效,次日仍然出现该问题

尝试2

  • 猜测: 是否有不合理的代码逻辑,未释放的资源,导致gc无法释放class(后续证明,思路正确)
  • 执行: 对job的代码逻辑进行自检,尝试修改可能存在的不合理之处
  • 结果: 无效,问题仍然存在

尝试3

  • 猜测: 有未释放的资源,且只有当特定的逻辑执行过后才会出现, 猜测是fastjson导致(heapdump中有大量的fastjson相关类)。
  • 执行:对StandaloneSessionClusterEntrypoint 进程进行heapdump,观测到大量的fastjson对象存活,猜测可能是fastjson导致的无法释放,遂在main函数中提前抛出错误,多次提交job。
  • 结果: 有效, metaspace的空间被正常回收了,但是无法确定是fastjson导致的该问题,但是定位到了问题代码的大致范围。

尝试4

  • 猜测: 存在问题逻辑不执行的情况下,不会导致metaspace OOM,首先排除是fastjson导致
  • 执行: 修改代码,在异常之前调用一次fastjson,再次反复提交
JSONObject o = JSON.parseObject("{}");if(true){thrownewRuntimeException();}
  • 结果: metaspace仍然被正常回收。

尝试5

  • 猜测: flink 的 userCodeClassloader没有被回收,导致其加载的类无法没正常gc。
  • 执行: 分析heapdump中的信息,发现有若干实例驻留在这里插入图片描述 观测其数量,约等于提交的次数 择其任一进行观察, 发现有一个相对特殊的引用在这里插入图片描述 查看得知该引用为某一个线程,其名称为:common-pool-evictor-thread 搜索得知该线程由jedis创建,联想到代码中存在使用jedis进行数据库的操作,遂查看在这里插入图片描述 猜测在jedis pool模式下需要使用独立的线程定期清除无效的链接,遂改为使用单连接的模式在这里插入图片描述 重新打包,进行反复提交的测试,metaspace被正常回收,问题解决

结论

  • flink job的jar中,尽可能减少引入三方jar, 将公共的jar放至libs文件夹中(官方建议),确保其不会被多次加载
  • 避免使用timer, pool等开启线程的操作,如有需要,改为自定义source的方式。
  • 尽可能保证执行job的classloader被正常的回收。
标签: flink jvm java

本文转载自: https://blog.csdn.net/qq_39086150/article/details/126032699
版权归原作者 我在大明湖边 所有, 如有侵权,请联系我们删除。

“记一次flink standalone模式下偶现Metaspace OOM的问题”的评论:

还没有评论