问题现象

服务跑几天内存从两百兆涨到两个多 G,重启后恢复,代码里没看到明显的大对象。

原因分析

模块级列表或字典不断追加且没有淘汰,对象一直被引用,垃圾回收无法释放。判断时先分清是 Python 内存泄漏 本身的配置问题,还是上游调用、运行环境带进来的差异;前者改配置就能收口,后者要沿着请求链路一层层往上找,处理顺序不能颠倒。先在出问题的机器上复现一次,把报错原文和发生时间记下来,再对着日志定位。

处理步骤

  1. 用 tracemalloc 定位增长点
  2. 给缓存加上限和过期策略
  3. 避免在循环里往全局容器塞对象

对应的命令或配置片段如下,可直接复制:

import tracemalloc
tracemalloc.start()
# 业务执行后
snap = tracemalloc.take_snapshot()
for s in snap.statistics('lineno')[:5]:
    print(s)

改动前把原配置备份一份,出问题时能马上回退,比现场找原因省时间。排查时把每一步的输出留下来,后面再遇到同类问题,对照日志就能判断是哪一层先出错的。

验证结果

压测一段时间后内存曲线趋于平稳,不再持续攀升,缓存命中率仍正常。

作者 9823189