CeleryD忽略并发参数求助:升级Celery后并发配置不生效
我来帮你一步步排查这个头疼的问题——明明设置了--concurrency=2,但Celery还是从RabbitMQ取8个任务执行,结合你的配置和Celery 4.x的特性,大概率是这几个原因:
1. 先确认配置是否真的被加载了
首先咱们得搞清楚,celeryd启动时有没有正确读取到你的/etc/default/celeryd配置。可以先手动模拟worker启动命令,直接在终端执行:
/home/ubuntu/dev/bin/python -m celery -A match2 worker --concurrency=2 --loglevel=INFO --chdir=/home/ubuntu/dev/match2/match2
如果手动执行后,并发数确实被限制为2,那说明问题出在celeryd服务没有正确加载配置文件;如果手动执行还是跑8个任务,那就是有其他配置在捣乱。
另外,去看你的Celery日志/var/log/celery/worker1.log,搜索“concurrency”关键词,找启动时的日志行,比如:
[202X-XX-XX XX:XX:XX,XXX: INFO/MainProcess] celery@yourhost ready.
[202X-XX-XX XX:XX:XX,XXX: INFO/MainProcess] concurrency: 2 (prefork)
如果这里显示的是8,那肯定是配置没生效。
2. 检查是否有其他配置覆盖了并发数
Celery的配置优先级是:环境变量 > Django settings > 命令行参数,所以咱们要排查这两个地方:
- 打开你的Django项目
settings.py,搜索CELERY_WORKER_CONCURRENCY,如果这个参数被设置成了8,那它会覆盖你命令行的--concurrency=2,把它改成2或者直接删掉。 - 检查系统环境变量,执行
echo $CELERY_CONCURRENCY,如果输出是8,说明这个环境变量在搞鬼,清空它再重启worker。
3. 注意prefetch-multiplier的坑!
你提到“从RabbitMQ消息队列中取出最多8个任务”,这很可能是预取乘数在作祟!Celery默认的prefetch-multiplier是4,意思是每个worker进程会提前从队列取4个任务缓存起来。你设置了--concurrency=2,那2*4=8,刚好是你看到的数量。
这个参数虽然不影响并发执行的任务数(还是2个),但会导致任务被提前从RabbitMQ取走,而且如果任务内存占用高,缓存的任务也会额外占内存。解决办法是把它改成1,让worker只取当前正在执行的任务,处理完再取下一个:
修改你的CELERYD_OPTS为:
CELERYD_OPTS="--concurrency=2 --prefetch-multiplier=1"
4. 彻底重启worker服务
修改配置后,一定要彻底停止再启动celeryd,不要用restart(有时候restart不会重新加载配置):
sudo service celeryd stop sudo service celeryd start
重启后再看日志,确认并发数和预取乘数的配置是否生效,然后观察任务执行情况,应该就不会同时跑超过2个任务了。
额外优化建议(针对你的场景)
因为你的任务会锁表且内存占用极高,还可以加上这两个参数进一步优化:
--max-tasks-per-child=1:让每个worker进程处理完一个任务就自动重启,避免内存泄漏累积。--time-limit=300:给每个任务设置超时时间(比如300秒),防止任务卡死占用资源。
修改后的CELERYD_OPTS可以是:
CELERYD_OPTS="--concurrency=2 --prefetch-multiplier=1 --max-tasks-per-child=1 --time-limit=300"
内容的提问来源于stack exchange,提问作者dengar81

