在我使用celery进行分布式任务调度时,出现了内存泄漏情况,32G的内存全被吃光(甚至还导致了我ssh登陆不上去的窘境zzz)。

我的运行场景时:2个worker节点做A任务(即下文截图中的fuzzer)、4个worker节点做B任务(即下文中的driller,吃内存小能手)。其中B工作节点,需要处理大量的任务(约上限为500,每个任务运行时可能需要1G内存)。

我本来以为1个工作节点执行完一项任务后,会释放任务申请的内存(毕竟一项任务执行完后它内部变量就不能引用了,python的垃圾回收机制应该会回收掉才对),这样的话最多同时有4个B工作节点在运行着,也就差不多消耗4G内存,绰绰有余!

然而,事实上,在celery中一个工作节点并不会释放一次任务的内存(至少从实验结果来看是这样的),而是不断累加。这样当我“轰炸式”的任务来袭时,明显机器就支撑不住了(囧)。那怎么办呢?经过上网搜索以及个人实验,觉得这个方法应该是可行的:

设置celery的每个worker能处理的最大任务数:CELERYD_MAX_TASKS_PER_CHILD = 10

一旦任务数超过这个数值时,当前worker进程就会被销毁(同时释放占用内存),并重新创建新的worker进程。

下图:一个worker节点,进程pid为15286,占用物理内存为10013324KB,约10GB,当前系统free内存5G。当任务数超过1 0个后,15286进程被销毁了,并新创建了19499进程,此时占用内存仅800M,且系统总free内存为10G,增多了! 

除此之外,还有一个选项也可以设置用于防止内存泄漏:CELERYD_MAX_MEMORY_PER_CHILD,单位是KB。一旦某个任务产生的内存超过这个限制的话(而不是指该任务导致当前worker节点的总内存超过这个限制),则这个任务仍然会执行下去,不过该任务执行完之后,当前worker进程就会被kill掉,重新创建新worker进程。

至此,problem solved!

results matching ""

    No results matching ""