You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+Celery多进程Gevent模式下无任务时内存泄漏问题

问题:Celery+gevent多进程模式下无任务时内存无故增长

环境与配置

启动命令

celery multi start 10 -P gevent -c 500 -A my-app -l info -E --without-gossip --without-mingle --without-heartbeat --pidfile='my-path' --logfile='my-path'

Django Celery配置

CELERY_IGNORE_RESULT = True
CELERY_WORKER_PREFETCH_MULTIPLIER = 100
CELERY_WORKER_MAX_TASKS_PER_CHILD = 400
CELERYD_TASK_SOFT_TIME_LIMIT = 60 * 60 * 12
CELERYD_TASK_TIME_LIMIT = 60 * 60 * 13

使用版本

  • celery==5.2.7
  • django==4.1.2

内存增长情况

内存增长情况

可能的原因分析

1. gevent协程的内存泄漏

gevent在高并发协程场景(你设置了-c 500)下,长期运行可能出现协程调度结构、内部管理对象的内存泄漏,即使无任务执行,这些未释放的资源也会缓慢占用内存。同时Celery 5.2.7与部分gevent版本的兼容性问题,也可能导致内存无法正常回收。

2. 预取任务机制的累积占用

你设置的CELERY_WORKER_PREFETCH_MULTIPLIER = 100会让每个worker进程预取100个任务到本地队列。如果RabbitMQ中存在大量待处理任务,worker会持续预取任务元数据(参数、消息头等),这些数据会驻留在内存中,即使当前没有任务执行也不会释放,导致内存持续上升。

3. celery multi的进程管理问题

用celery multi启动10个worker进程后,每个进程都维护独立的gevent协程池。如果进程内部的资源回收逻辑存在缺陷,或者celery multi的进程监控机制本身有内存泄漏,会导致无任务时内存缓慢增长。

4. Django全局资源未释放

Celery worker启动时会加载Django环境,数据库连接池、缓存连接等全局资源如果没有正确关闭或回收,即使无任务,这些资源也会占用内存。加上gevent的monkey-patch可能干扰Django的资源释放逻辑,导致对象无法被GC回收,形成累积泄漏。

5. 事件与日志系统的内存占用

启动命令中的-E参数开启了Celery事件系统,即使无任务,事件系统也会持续维护内部状态或缓冲区;同时日志文件的写入缓冲区如果未及时刷新,也会占用额外内存,长期累积导致内存增长。

排查与解决建议

  • 调整协程与预取参数:将协程数-c从500降至100以内,CELERY_WORKER_PREFETCH_MULTIPLIER调至10或更低,观察内存变化。
  • 添加内存触发的进程回收:除了CELERY_WORKER_MAX_TASKS_PER_CHILD,新增CELERY_WORKER_MAX_MEMORY_PER_CHILD配置,当进程内存达到阈值时自动重启,强制释放资源。
  • 关闭事件系统:去掉启动命令中的-E参数,停止事件订阅,验证内存是否停止增长。
  • 适配gevent版本:升级或降级gevent到与Celery 5.2.7兼容的稳定版本(比如21.12.0),排除版本兼容性导致的泄漏。
  • 清理Django资源:在worker启动后手动清理不必要的全局资源,或在任务完成后显式关闭数据库连接,避免连接池长期占用内存。

内容的提问来源于stack exchange,提问作者rmaleki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 04:25:38