解决内存泄漏的通用思路

问题背景

之前在做扫描器时,有一个功能是:生成任务实例。

使用场景是:用户在web页面上点击启动按钮,就可以立即运行指定的任务(比如指定哪些POC对哪些资产做漏洞扫描);定期运行扫描任务

因为”生成任务实例”时可能需要比较久的时间,并且有很多其他业务逻辑,所以这里由后台进程来生成任务实例,实现”异步”的效果。

image

在线上发现一个问题:”后台创建任务实例的进程”运行一段时间后,内存占用越来越大。

虽然当时能力有限,并没有找到”内存不断增长”的原因,但是最终还是解决了这个问题。

怎么解决的

我当时的想法是,虽然找不到原因,但是重启大法好啊,我可以处理N个任务后,删除这个”后台创建任务实例的进程”再新建进程。

项目中我用的是python语言,celery框架,刚好celery提供了两个参数

1
2
3
4
5
6
7
8
9
10
11
12
root@50f41bfab20a:/# celery worker --help
...
--max-tasks-per-child MAX_TASKS_PER_CHILD, --maxtasksperchild MAX_TASKS_PER_CHILD
Maximum number of tasks a pool worker can execute
before it's terminated and replaced by a new worker.
--max-memory-per-child MAX_MEMORY_PER_CHILD, --maxmemperchild MAX_MEMORY_PER_CHILD
Maximum amount of resident memory, in KiB, that may be
consumed by a child process before it will be replaced
by a new one. If a single task causes a child process
to exceed this limit, the task will be completed and
the child process will be replaced afterwards.
Default: no limit.

可以指定内存超过多少、处理多少任务后,生成新的进程来处理任务。

我就靠这两个参数解决​了问题。

总结

后面我在做安全评估时,发现其他业务线有php语言开发的程序也是这种模式:使用子进程处理任务,处理N个任务后,”重新创建”子进程。

所以,凡是业务场景允许”进程重启”的,应该都可以用这种模式来解决”内存泄漏”。

难解决的是”长时间持续运行的程序”出现的”内存泄漏”

参考

既然每个程序占用的内存都是操作系统管理的,为什么内存泄漏还是个问题? - pansz的回答 - 知乎