IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> flink taskmanager metaspace OOM -> 正文阅读

[大数据]flink taskmanager metaspace OOM

现象

flink 程序打成jar多次提交后,有taskmanager 节点挂掉,这个现象而且经过多次试验后发现是必现,日志如下

The metaspace out-of-memory error has occurred. 
This can mean two things: either Flink Master requires jobmanager.memory.jvm-metaspace.size a larger size of JVM metaspace to load classes or there is a class loading leak. In the first case jobmanager.memory.jvm-metaspace.size  configuration option should be increased. 
If the error persists (usually in cluster after  several job (re-)submissions) then there is probably a class loading leak in user code or some of its dependencies which has to be investigated and fixed. The Flink Master has to be shutdown

背景知识

flink里面加载器,分为 ParentFirstClassLoader ChildFirstClassLoader ,ChildFirstClassLoader是默认的类加载器

MetaSpace分析

从报错日志分析来看,一种是metaspace 真的非常小,另外的原因就是代码中存在内存泄漏,class 没有被回收,很明显问题应该在内存泄漏,metaspace这个问题应该还是出现的很少的。

微服务

通常的微服务通常启动过,就不会有新加载类的情况,所以很少出现此类问题,有些场景比如,部分用到反射的场景,可能会有这个问题

计算场景

计算平台每收到一个新的job,就要加载用户类,所以如果用户程序或者第三方jar有内存泄漏的情况就会导致task 节点的metaspace 一直增加,直到OOM

代码分析

代码逻辑
消费kafka--------->计算-------------->写es/kafka

写ES 用到的ES类

public RestHighLevelClient restHighLevelClient;

步骤1

先简单修改下代码测试下

  1. 消费kafka--------->输出 重试N次,没有问题
  2. 消费kafka--------->计算----->输出 重试N次,没有问题
  3. 消费kafka--------->计算----->写es 问题复现
  4. 消费kafka--------->计算----->写kafka 重试N次,没有问题

经过上面的尝试
问题的方向应该在写es上

步骤2

查阅相关的资料

  1. 有没有任务里面有线程没有被关闭,这些线程可能还持有class 对象的引用
  2. 缓存相关的东西
  3. JDBC 相关的类,放在lib 目录下,这样只加载一次
  4. RuntimeContext.registerUserCodeClassLoaderReleaseHookIfAbsent() 注册一个钩子函数,手动释放掉类加载器

在这里插入图片描述

flink 调试类加载

步骤3

用MAT 工具分析
确实有很多类重复,每次提交相同的job,类就是会被加载,在测试的时候,用 jvisualvm 打开可以直观看到加载类的变化,也可以执行GC,这里要注意的是,一下要在多次GC之后,再dump,这样剩下的类才是没有办法卸载的
在这里插入图片描述

查看leak suspects
在这里插入图片描述
这里注意这个红色的,和ES相关,引起了我的注意

在这里插入图片描述

分别得到从这个对象到GC root的路径
在这里插入图片描述
GC root 到这个对象的最短路径
在这里插入图片描述
黄点表示GC ROOT
path to GC roots
merge shortest paths to GC roots
这两个的区别可以从图标上看出来
在这里插入图片描述

步骤4

从上面的分析再思考下,RestHighLevelClient关联的对象大小排第一,这个类应该在任务结束之后会被回收才对,为什么没有被回收呢?看下代码
RestHighLevelClient 对象确实有close方法,但是没有执行
修改下代码,重试下看看

 @Override
    public void close() throws Exception {
        super.close();
        RestHighLevelClient restHighLevelClient = esUtil.getRestHighLevelClient();
        restHighLevelClient.close();
    }

步骤5

问题解决,提交N次任务,没有发生OOM 异常,多次提交任务后,taskmanager的metaspace 虽然会增加,但是触发full gc之后,类能够被卸载,metaspace 会减小

总结

虽然最后从文章来看,解决的比较容易,中间其实也看了很多的资料,最开始用MAT工具没有看出结果,下面是从这次问题可以收获的几个知识点

  1. 类卸载的时机
  2. classloader 卸载时机
  3. MAT 工具的使用
  4. jvisualvm 使用
  5. flink 类加载机制
  6. jvm 内存结构
  7. 解决问题的思路,比如可以不段缩小代码执行的范围

其它

之前这个问题一直都存在,一直没有解决,这次小长假的计划就是解决这个问题,最后的结果是完美的。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 23:15:00  更:2022-04-06 23:15:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:39:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码