HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

SysOM 案例解析:消失的内存都去哪了

  • 2022-07-11
  • 本文字数:1902 字

    阅读完需:约 6 分钟

SysOM 案例解析:消失的内存都去哪了

一、 问题现象


客户收到系统告警,K8S 集群某些节点 used 内存持续升高,top 查看进程使用的内存并不多,剩余内存不足却找不到内存的使用者,内存神秘消失,需要排查内存去哪儿了。



执行 top 指令并按内存排序输出,内存使用最多的进程才 800M 左右,加起来远达不到 used 9G 的使用量。


二、问题分析

2.1 内存去哪儿了?


在分析具体问题前,我们先把系统内存分类,便于找到内存使用异常的地方,从内存使用性质上,可以简单把内存分为应用内存和内核内存,两种内存使用量加上空闲内存,应该接近于 memory total,这样区分能够快速定位问题的边界。



其中 allocpage 指通过 __get_free_pages/alloc_pages 等 API 接口直接从伙伴系统申请的内存量(不包含 slab 和 vmalloc)。

2.1.1 内存分析


根据内存大图分别计算应用内存和内核内存,就可以知道是哪部分存在异常,但这些指标计算比较繁琐,很多内存值还存在重叠。针对这个痛点,SysOM 运维平台的内存大盘功能以可视化的方式展示内存的使用情况,并直接给出内存是否存在泄漏,本案例中,使用 SysOM 检测,直接显示 allocpage 存在泄漏,使用量接近 6G。


2.1.2 allocpage 内存


那既然是 alloc page 类型的内存占用多,是否可以直接从 sysfs、procfs 文件节点查看其内存使用了?很遗憾,这部分内存是内核/驱动直接调用 __get_free_page/alloc_pages 等函数从伙伴系统申请单个或多个连续的页面,系统层面没有接口查询这部分内存使用详情。如果这类内存存在泄漏,就会出现"内存凭空消失"的现象,比较难发现,问题原因也难排查。针对这个难点,我们的 SysOM 系统运维能够覆盖这类内存统计和原因诊断


所以需要进一步通过 SysOM 的诊断利器 SysAK 动态抓取这类内存的使用情况。

2.2 allocPage 类型内存排查

2.2.1 动态诊断


对于内核内存泄漏,我们直接可以使用 SysAK 工具来动态追踪,启动命令并等待 10 分钟。


sysak memleak -t page -i 600
复制代码



诊断结果显示 10 分钟内 receive_mergeable 函数分配的内存有 4919 次没有释放,内存大小在 300M 左右,分析到这里,我们就需要结合代码来确认 receive_mergeable 函数的内存分配和释放逻辑是否正确。

2.2.2 分配和释放总结


1)page_to_skb 每次会分配一个线性数据区为 128 Byte 的 skb。

2)数据区调用 alloc_pages_node 函数,一次性从伙伴系统申请 32k 内存(order=3)。

3)每个 skb 会对 32k 的 head page 产生一次引用计数,也就是只有当所有 skb 都释放时,这 32k 内存才释放回伙伴系统。

4)receive_mergeable 函数负责申请内存,但不负责释放这部分内存,只有当应用从 socket recvQ 中把数据读走才会对 head page 引用计数减一,当 page refs 为 0 时,释放回伙伴系统。

当应用消费数据比较慢,可能会导致 receive_mergeable 函数申请的内存释放不及时,而且最坏情况一个 skb 会占用 32k 内存,使用 sysak skcheck 检查 socket 接收队列和发送队列残留情况。



从输出可以知道,系统中只有 nginx 进程的接收队列有残留数据,socket  fd=11 的 Recv-Q 有接近 3M 的数据没有接收,通过直接 kill 146935,系统内存恢复正常了,所以问题根本原因就是 nginx 没有及时收走数据了。

三、问题结论


经过与业务方沟通,最终确认是业务配置问题,导致 nginx 有一个线程没有处理数据,从而导致网卡驱动申请的内存没有及时释放,而 allocpage 内存又是无法统计的,从而出现内存凭空消失的现象。

3.1 结论验证


接收队列真的有数据残留吗,这里结合 crash 工具的 files 指令通过 fd 找到对应的 sock:


socket = file->private_datasock = socket->sk
复制代码



通过多次观察,发现 sk_receive_queue 上的 skb 长时间没有变化,这也证明了 nginx 没有及时处理接收队列上的 skb,导致在网卡驱动中分配的内存没有释放。

四、内存泄漏疑点


在排查过程还遇到一个非常较困惑的地方,sockstat 和 slabtop 看检查 tcp mem 和 skbuff_head_cache 使用都很正常,导致进一步掩盖了网络占用的内存。

tcp mem = 32204*4K=125M



skb 数量在 1.5 万~3 万之间。



按照前面分析,一个 skb 最坏情况占用 32k 内存,那么 2 万个 skb 最大也就占 600M 左右,怎么会占用几个 G 了,难道分析有问题?如下图所示,skb 的非线性区可能还存在若干个 frag page,而每个 frag page 又可能由 compund page 组成。



用 crash 实际读取 skb 内存发现,有些 skb 存在 17 个 frag page,并且数据大小只有 10 Byte。



解析 frag page 的 order 为 3,意味着一个 frag page 占用 32k 内存。



极端情况下,一个 skb 可能占用(1+17)*8=144 页,上图 slabinfo 中 skbuff_head_cache 活跃 object 数量为 15033 个,所以理论最大总内存 =144*15033*4K = 8.2G,而我们现在遇到的场景消耗 6G 的内存是完全有可能的。

2022-07-11 10:551731

评论

发布
暂无评论
发现更多内容

MySQL性能优化(七):MySQL执行计划,真的很重要,来一起学习吧

xcbeyond

MySQL MySQL性能优化 执行计划

JDK1.8新特性(一):JDK1.8究竟有哪些新特性呢

xcbeyond

jdk8 新特性 JDK1.8新特性

课程总结

Thrine

指数 | 2020年6月北京BGP机房网络质量评测报告

博睿数据

评测 博睿宏远 指数

详解区块链应用市场与落地应用现状

CECBC

MySQL性能优化(五):为什么查询速度这么慢

xcbeyond

MySQL 查询优化 MySQL性能优化

海南七星彩网站源码结算功能开发

网站,小程序,APP开发定制

MySQL性能优化(六):常见优化SQL的技巧

xcbeyond

MySQL MySQL性能优化 SQL优化 优化技巧

SaaS是「包治百病」的良药吗?

ToB行业头条

博睿宏远获颁“2020开发与技术企业服务奖”

博睿数据

运维自动化 开发工具 博睿宏远

没错,用三方 Github 做授权登录就是这么简单!(OAuth2.0实战)

程序员小富

Java GitHub oauth2.0

MySQL 连接查询超全详解

X先生

MySQL 数据库

HashMap学习总结

大刘

hashmap hash

腾讯的区块链为何败给了老干妈的“萝卜章”?

ToB行业头条

MySQL 三万字精华总结 + 面试100 问,和面试官扯皮绰绰有余(收藏系列)

大头星

Java MySQL 面试

分布式存储系统doris

Thrine

未来的智慧城市:未来的城市生活愿景

网站,小程序,APP开发定制

数据结构学习心得

程李文华

路过,凌晨2点的南京

小天同学

总结 思考 个人感悟 夜归人

第6周作业

andy

第6周总结

andy

如何在 3 个小时内完成一周的工作

escray

你与30W奖金只差一个 Apache Flink 极客挑战赛的报名

Apache Flink

flink

从一盏路灯,看亿万级联接的智能之路

华为云开发者联盟

人工智能 物联网 智能设备 华为云

案例解析丨金蝶K/3 Wise接入华为云RDS数据库SQL Server

华为云开发者联盟

MySQL 数据库 Serverless 数据 华为云

再强调一遍, 我为什么不建议大家接外包干私活?

非著名程序员

程序员 外包 提升认知 接私活

Spring循环依赖及解决方式

张sir

Java spring 循环依赖

第6周课后练习-请简述CAP原理

Dawn

极客大学架构师训练营

MySQL性能优化(四):如何高效正确的使用索引

xcbeyond

MySQL 索引 MySQL性能优化

开源数据交换(client)

李孟聊AI

Java 大数据 flink spark 数据交换

天元MegEngine深度学习框架贡献者计划全面启动!

flashrunrun

人工智能 学习 开源 AI

SysOM 案例解析:消失的内存都去哪了_文化 & 方法_龙蜥社区系统运维SIG_InfoQ精选文章