记一次内存泄漏问题的排查经历
源宝导读:随着系统越来越庞大,越来越复杂,疑难杂症问题也越来越多。本文将介绍明源研发协同平台团队针对一次内存泄露问题的排查过程和技术探索。
一、背景
内存泄漏,一个说大不大说下不小的瑕疵。作为开发者,我们都很清楚内存泄漏是我们代码问题导致的。但是话说回来,泄漏后果会很严重嘛?这不好说,如果对服务器内存的影响只有几个百分点,又或者对应用没有什么致命影响,那么修补内存泄漏就像鸡肋一样,“食之无味,弃之可惜”。反之内存泄漏也可能导致服务不可用,严重影响用户体验。
二、问题
19年年初,协同平台后台服务开始间歇性非正常重启,每次重启耗时2-5分钟,重启期间服务不可用;并且事发前用户触发的部分任务没有重试机制,一些中间状态的数据需要人工修复。
初步排查是程序池内存溢出引起的IIS自动回收,监控看板显示服务器内存从50%瞬间涨到100%,十几分钟之后触发回收,内存才彻底降下来。
此后重启事件陆续不断,间隔从数小时到数天不等,每次重启前毫无征兆,没有规律可循,下图是服务的内存走势图。
三、事件分析
通常内存泄漏最常规的做法是抓取Dump包,然后分析Dump包中的堆栈数据。但这次内存泄漏并非缓慢上升,而是瞬间将内存吃满,没有多余的硬件资源供抓包工具使用。更重要的是这个后台服务职责过重,也非常重要,属于一个在线系统,随便都有用户访问,抓包工具在进行抓包过程中会中断进程,影响服务使用。所以抓取Dump包的方案被暂时搁置。
在翻遍所有日志没有找到蛛丝马迹之后,决定采用分治策略排除法,先将事故影响的范围慢慢缩小。
四、垂直拆分
前文提到后台服务职责过重,需要进行拆分,这个是年初团队达成的共识,方案是先将后台作业任务独立出来,此次事件是个契机。新增一个调度服务,将现有定时作业和主动长时作业两块逻辑包含进去。拆分之后,主服务恢复正常,重启问题转移至新增的调度服务,风险随之降级,虽然问题没有解决,但是两个服务的事故级别是不一样的,主服务恢复正常后,至少不会对用户产生直接影响。
虽然是一次投鼠忌器的尝试,好在结果符合预期,满足分治的需求,现在已经可以确定,元凶肯定就在调度服务的代码中。
五、监控埋点
现在范围缩小了许多,定时作业和主动长时作业两大类,其中的子任务加起来不超过20个,将所有任务的开始和结束各记一次埋点。随后观察重启发作时间点与两大类后台作业的开始时间进行匹配,所有的任务都可以正常的开始,并正常的结束,没有一类任务的执行时间与重启时间点完全匹配,后台任务的嫌疑全部排出。
六、动态抓包
排查陷入了僵局,再次观察监控看板,分析现有数据:调度服务的进程内存,正常值在400m-700m之间波动,出现异常时内存在2分钟内,由正常值上升至最高值,最高值接近系统总内存,这个与最初的症状有所不同,起初内存是90度直线瞬间吃满,现在是在2分钟内45度吃满内存。有了2分钟的缓冲期,可能与内存扩容有关,也可能与垂直拆分有关,原因不得而知,但这一点变化使得Dump抓包成为可能。
这里推荐使用ProcDump,ProcDump是一个轻量级的Sysinternal团队开发的命令行工具,它的主要目的是监控应用程序的CPU内存异常动向,并在此异常时生成crash dump文件,供研发人员和管理员确定问题发生的原因。你还可以把它作为生成dump的工具使用在其他的脚本中。
根据调度服务内存正常值的区间范围,内存阈值设置为1.5G,超过1.5g认为内存异常。按照ProcDump官网的介绍,ProcDump可以在阈值条件(内存、CPU、异常)到达时,自动触发Dump抓取,但是我部署在服务器ProcDump在一定时间后会出现假死现象,不能后台作业,也不知道下一次重启什么时候来临。无奈临时编写一个小工具,需求很简单,实时监控进程内存,10s轮询一次,超过阈值执行“procdump.exe -ma dotnet.exe“命令抓取Dump,下面是关键代码:
七、内存分析
在小工具完成的第二天便成功捕捉到了传说的“黑匣子”,如空难事故中一样,它记录了程序在宕机前的性能指标。
堆中数据显示,两个字符串数组占据了大部分内存空间,进一步跟踪到是一个zip包解压函数,在读取文件流时,while循环的退出条件判断有误,引起了死循环,无论系统内存有多大,都可以在短时间将服务器内存吃满。代码并非每次都会进来,具有一定的随机性,取决于用户的操作,所以重启没有规律。
这段业务属于长时作业任务,在上面第五步的监控埋点中,记录了定时作业和主动长时作业两大类的执行结果,唯独这个被动长时作业任务成了漏网之鱼,没有纳入监控体系。
八、总结
虽然修复这个Bug的工作量很小,但Bug持续时间长,影响较大。事后团队做了两点改进措施,一是研发流程中加入代码扫描工具,将这类“低级错误”拦截在开发阶段,避免提交到测试环境和生产环境;二是继续完善了现有监控数据,将被动长时作业任务的执行情况,展示在监控看板上,如果某个任务执行失败,或者只有开始没有结束,监控看板会及时发送提醒,为排查类似问题提供线索,快速定位类似问题。
记一次内存泄漏问题的排查经历相关推荐
- 华为云数据库GaussDB(for Cassandra)揭秘第二期:内存异常增长的排查经历
摘要:华为云数据库GaussDB(for Cassandra) 是一款基于计算存储分离架构,兼容Cassandra生态的云原生NoSQL数据库:它依靠共享存储池实现了强一致,保证数据的安全可靠. 本文 ...
- 一个C++工程内存泄漏问题的排查及重现工程
最近遇到一个C++工程内存泄漏的问题,经过排查,发现原来是 map 的使用有问题,本文记录了排查的过程,并给出一个类似的工程代码. 起因 某日,运维反馈生产环境某台设备出现问题,经组长排查,有两个工程 ...
- IOS内存泄漏动静态方法排查
文章目录 简单观察内存 静态分析 概念 可排查到的问题 具体的操作 部分问题及解决 动态分析 概念 具体的操作 数据分析 statistics allocations list generations ...
- unity如何检测内存泄漏_如何排查Java内存泄漏?看懂这一篇就够用了
原文:https://www.toptal.com/java/hunting-memory-leaks-in-java 作者:Jose Ferreirade Souza Filho 译者:Emma来源 ...
- 一次Java内存泄漏调试的有趣经历
本文由 ImportNew - yizhe 翻译自 allegro.tech.欢迎加入翻译小组.转载请见文末要求. 人人都会犯错,但一些错误是如此的荒谬,我想不通怎么会有人犯这种错误.更没想到的是,这 ...
- 记一次SOFA内存泄漏排查过程
记一次内存泄漏排查过程 起因 某天中午大家还在安静的午休,睡得正香的时候突然被一阵手机滴-滴滴直响短信惊醒.一看是应用的服务器告警并且对应服务的所有机器都在告警"健康检查失败,自动拉下线&q ...
- 一次完整的JVM堆外内存泄漏故障排查记录
前言 记录一次线上JVM堆外内存泄漏问题的排查过程与思路,其中夹带一些JVM内存分配机制以及常用的JVM问题排查指令和工具分享,希望对大家有所帮助. 在整个排查过程中,我也走了不少弯路,但是在文章中我 ...
- C++内存泄漏排查以及几个工具
近期排查老项目App的偶发闪退问题过程中,发现程序竟然有内存泄漏的情况,表现为连续运行多天后程序占用的虚拟内存和物理内存都会持续升高,经过排查修改,找出了多处内存泄漏,现对排查过程做个小结. 内存泄漏 ...
- 在线排查内存泄漏的步骤
一.在线排查内存泄漏的步骤 想到内存泄漏问题的排查,很多开发会想到使用 Valgrind.使用 Valgrind 有几个局限: 需要安装 Valgrind 需要启停服务进程 影响服务进程性能 依赖于测 ...
最新文章
- 《Linux From Scratch》第二部分:准备构建 第三章:软件包与补丁- 3.1. 简介
- YOLO窥见黑夜|YOLO in the Dark让黑夜里的目标检测成为可能
- VirtualBox的四种网络连接方式
- python json.loads()中文问题-python处理json数据中的中文
- Linux服务器中实现文件夹可写不可删除
- emacs org-mode文件转html文件
- C语言durand kerner算法求近似根roots(附完整源码)
- JVM学习笔记(四)
- mysql5.6.13_MySQL-5.6.13解压版(zip版)安装配置教程
- “入洞房与度蜜月”的来历
- linux设置系统自动开机,Linux系统中设置开机自动运行的两种方法
- win10python3.6.3安装_Win10Python3.6安装impyla
- SlidingMenu 源码分析
- [Java] 蓝桥杯ALGO-100 算法训练 整除问题
- matlab 平滑曲线连接_如何使用Affinity Designer for mac编辑矢量曲线和形状
- windows ping不通虚拟机ip地址
- 计算机桌面锁定了没设密码怎么解锁,屏幕锁定怎么解锁?
- ARM920T的MMU与Cache ——转载
- 对与连连看求解算法的研究
- 域名邮箱什么,如何开通自定义邮箱后缀的邮箱?