之前在我们云备份产品的Agent端,为了优化增量备份效率,开发团队设计了设计了以下核心模块:缓存上下文记录模块 / 备份数据写入模块 / 操作日志记录模块等。设计目的是避免重复计算增量位置,但是由于对备份数据写入逻辑中文件流未关闭,导致上线后出现了Agent 机器内存泄漏后备份任务异常中断。
基于以上案例,我将在本文中总结在遇到内存泄漏问题时应该如何分析,并定位问题。
分析方法:控制变量法+排除法
这次问题中我们采用了控制变量法+排除法结合的方式分析出了内存泄漏点。
核心思路:
逐步排除可疑模块,定位泄漏点:通过联合开发人员进行 注释/禁用特定代码逻辑,观察内存是否恢复稳定。若禁用某模块后内存泄漏消失,则该模块为问题根源。以下是详细步骤:
1. 确定怀疑范围
根据业务场景和内存泄漏现象,优先怀疑以下模块:
任务上下文缓存管理(如静态字典
ConcurrentDictionary
)。M365 API调用(如未释放的HTTP连接、响应流)。
备份数据写入(如文件流未关闭、缓冲区未清理)。
2. 控制变量法实施步骤
步骤①:禁用API调用后的资源处理
操作:
注释M365 API调用后的资源释放逻辑(如关闭响应流)
重新测试,观察内存变化。
结论:
若内存增长加速 → API调用存在资源未释放问题。
若内存趋势不变 → 排除此模块。
步骤②:关闭备份数据写入模块
操作:
注释备份数据写入的代码(如文件流操作):
重新测试,观察内存是否稳定。
结论:
若内存泄漏消失 → 文件流未关闭导致泄漏。
步骤③:注释缓存逻辑
注释或删除
BackupJobManager.AddContext
方法中的缓存写入代码:重新编译并部署Agent。
使用相同测试场景(如高频触发备份任务)运行,观察:
内存是否仍持续增长(通过简单日志或任务管理器观察)。
是否仍抛出
OutOfMemoryException
。
结论:
若内存不再增长 → 确认缓存逻辑是泄漏主因。
若内存仍增长 → 继续排查其他模块。
3. 修复验证
操作:
修复文件流未正确关闭的逻辑。
重新运行相同测试场景,确认内存指标稳定。
附:分析方法二:日志分析
核心思路:
通过事务耗时和异常日志定位问题
操作步骤:
添加详细日志:
在关键事务(任务上下文缓存管理 / M365 API调用 / 备份数据写入 等)中记录时间戳、内存占用、耗时、异常信息:
复现问题:
运行Agent直到内存溢出,分别收集初期和后期的日志。
对比分析:
耗时增长:若某事务(如“生成任务上下文”)耗时从50ms逐步增加到500ms,可能因缓存膨胀导致性能下降。
内存日志:若
ContextCacheSize
字段值持续增加且不回落,直接指向缓存泄漏。
总结
优先使用控制变量法:快速定位问题模块,适合对代码结构较熟悉的场景。
日志分析作为补充:依赖详细日志,适合需要量化分析的场景(如耗时、缓存大小趋势)。
最终验证:无论哪种方法,均需通过修复代码和观察内存指标确认结果。