CDH yarn集群GC告警内存泄漏, 结合源码排查分析

问题

GC超阈值

在之前的5分钟内,垃圾收集花费的平均时间为每分钟36.4秒。临界阈值60%
NODE_MANAGER_GC_DURATION has become bad: Avgrage time spent in garbage collection was 36.4 seconds(s) per minute over the prevoies 5 minute(s). Critical threshold: 60%


The healthy test result for YARN_RESOURCEMANAGERS_HEALTH has become concerning

排查

查看NodeManage日志

日志中每隔几秒就会发生gc且老年代回收( CMS )的时间比较久


官网问题查询
关键字: NODE_MANAGER_GC_DURATION

从社区的答复来看, 大多数的建议是调整NodeManager的堆大小和监控值, 但是并没说到问题的原因, 接着继续排查吧

点击图标库, 查看进程使用情况

发现最近时间段堆内存一直接近最大值, 且每次回收掉的内存非常少; 查看7天数据gc和堆内存的占用处于持续上升的状态, 初步定位是内存泄漏




查看30天发现29号的时候内存突降, 之后又开始持续上升至峰值徘徊, 其实29号的前几天也是不正常的


查看日志和进程信息, 29号的9点确有异常, 触发了yarn节点重启机制 , 发生内存溢出生成了dump文件


jvm运行参数

重启日志

dump文件

内存泄漏

yarn默认没有开启gc的打印, 需要自己在cdh进行配置, 搜索JAVA_GC_ARGS,在对应位置填上-Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails , 配置生效需要重启该节点( 可选项 )

1. 查看gc详情

jstat -gcutil 25678 3000 100
从图中来看明显是有问题的;YGC和FGC代表新生代和老年代gc的次数, 每隔几秒次数就会递增, 且老年代的空间一直没有回收掉

2. 分析在堆中对象的数量和占用字节

执行su -s /bin/bash -c ''/usr/java/jdkl.8.0_202-amd64/bin/jmap -histo:live 20886" yarn | more

  • 如果提示jdk版本的报错, jmap前加上运行参数的全路径;
  • 如果报Unable to open socket file: target process not responding or HotSport VM not loaded, 则切换到进程的用户;
  • 如果切换时报This account is currently not available, 则可用root用户su -s指定用户去执行命令

从命令结果来看, 占用最多的是字符串和byte数组, 但是不知道里面的内容是什么, 所以需要mat去分析堆中对象的详情

3. 将dump文件导入到mat中

su -s /bin/bash -c '/usr/java/jdkl.8.0_202-amd64/bin/jmap -dump:format=b,file=/tmp/nnm.dump 20886' yarn, 如果已经发生了内存溢出生成了dump文件, 则不需要执行这一步

总览图
点击Histogram->右键对象List objects->with outgoing references

发现缓存大量spark job的shuffle索引文件路径, 但实际上appcache下并没有文件, 所以推断这个是shuffle的临时文件, 查阅源码证明推断正确, ExternalShuffleServiceexecutorRemoved()applicationRemoved()方法; 为什么这类文件会这么多, 在哪个地方引用的呢?

appcache目录结构

解决思路

  1. 去spark的web界面去查看该job执行时,是否发生大量的shuffle操作, 如果是可尝试去调整代码上或job运行参数, 以来减少数据的混洗

通过分析, 该job( application_1588204334324_0246 )其实早已经执行完了, 却还是一直触发gc的告警, hdfs上本地的shuffle文件也不存在了, 进一步推断是yarn缓存管理的问题

  1. 寻找spark yarn中控制shuffle缓存的配置并修改

排查spark源码

根据调用堆栈搜索shuffleIndexCache,ShuffleIndexInformation,CacheBuilder, 在源码中找到关键类ExternalShuffleBlockResolver


缓存键值分布

 String indexCacheSize = conf.get("spark.shuffle.service.index.cache.size", "100m");
    CacheLoader<File, ShuffleIndexInformation> indexCacheLoader =
        new CacheLoader<File, ShuffleIndexInformation>() {
          public ShuffleIndexInformation load(File file) throws IOException {
            return new ShuffleIndexInformation(file);
          }
        };
    shuffleIndexCache = CacheBuilder.newBuilder()
      .maximumWeight(JavaUtils.byteStringAsBytes(indexCacheSize))
      .weigher(new Weigher<File, ShuffleIndexInformation>() {
        public int weigh(File file, ShuffleIndexInformation indexInfo) {
          return indexInfo.getSize();
        }
      }).build(indexCacheLoader);

查看源码得知缓存的统计是根据索引文件大小叠加的, 即ShuffleIndexInformation的size相加; 根据上面的缓存键值分布图做空间推测

  • ShuffleIndexInformation的size平均为152字节, 则100mb可存放的对象数为
    689852 个 = 100(mb) * 1024 * 1024 / 152
  • key是File类型的, 每个对象占用920字节, 则缓存中key占用的空间为
    605 mb = 689852 * 920 / 1024 / 1024

结合mat的总览图, 缓存对象占用817mb, 那么和推断的值705mb = 605+100基本是吻合的; spark管理这一块的缓存只累加了value的文件容量, 而忽略了key占用的内存, 个人感觉这一块会有隐患, 如果ShuffleIndexInformation的size值很小, 那么key的数量会非常的多, 如果内存配置不够大那么发生内存溢出的概率比较大

更改源码

在github上查看这个类的提交记录没有找到相关的修复, 提下issue或pr看官方有什么答复; 有个要注意的小点, 源码中缓存使用的是LocalCache.LocalLoadingCache, 调用get方法的时候会同时load进缓存中, 且ExternalShuffleBlockResolver中有提供清理过期文件的操作

  • 方案1: CacheLoader构造时重写weigher()方法中加入key的容量统计
  • 方案2: 执行清理操作时同时清理缓存

Spark Issues

通过查看 Spark官方问题列表, 看到了类似的问题, 不过我的pr没被采纳已经关闭了

issue搜索截图

SPARK-33206
我的PR-SPARK-33710

查看hadoop的源码

堆中存在着大量路径信息, 所以可以尝试去搜索关键字如 appcache, 结合调用堆栈可找到相关类ResourceLocalizationService,YarnConfiguration,LocalCacheCleaner,查看源码得知yarn提供资源缓存的清理, 默认值10分钟执行一次,清理的阈值为10G

解决

  1. 调整Yarn NodeManager堆内存, 默认的1GB数值太小; 在有多个job运行时, executor的数量也会增加, 每个executor占用100m的index缓存, 很快就到达阈值
  2. 调整shuffle index大小或更改源码( 不推荐 );

参考

Apche贡献指南
Hadoop源码
Spark源码
Yarn ResourceManager内存泄漏
大数据运维日常-YARN 运维、巡检、监控、调优、排障
CDH文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容