問題發現
本來top命令查看服務器實時內存情況, 突然發現32G內存 celery 佔用到12%, 內存佔用都快4G了.
top
命令下,M
鍵開啓按MEM
列排序的進程列表,按H
則查看線程列表,由於worker
沒有子線程,所以只顯示一條記錄;- 按
c
命令,開始COMMAND
列詳細情況,可以找到對應的進程啓動者;- 按
o
鍵,開啓篩選功能,輸入COMMAND=celery
只顯示celery
名的進程列表;
原因
默認情況下,celery的worker是工作進程可以被新任務替換之前執行的最大任務數, 默認值是沒有限制。
見官網說明
"""
celery配置
"""
from celery.schedules import crontab
# 中間人
BROKER_URL = 'redis://:[email protected]/x'
worker_prefetch_multiplier = 4 # celery worker併發數
worker_max_tasks_per_child = 2 # 每個worker最大執行任務數
# 指定時區,不指定默認爲 'UTC'
CELERY_TIMEZONE = 'Asia/Shanghai'
# 指定導入的任務模塊
CELERY_IMPORTS = (
'celery_app.tasks',
)
需要配置celery設置 但是官網寫的參數在執行執行過程中發生錯誤 "無法將新設置名稱與舊設置名稱混合使用"
Cannot mix new setting names with old setting names, please
rename the following settings to use the old format:
worker_max_tasks_per_child -> CELERYD_MAX_TASKS_PER_CHILD
worker_prefetch_multiplier -> CELERYD_PREFETCH_MULTIPLIER
需要修改配置名稱:
"""
celery配置
"""
from celery.schedules import crontab
# 中間人
BROKER_URL = 'redis://:[email protected]/x'
CELERYD_PREFETCH_MULTIPLIER = 4 # celery worker併發數
CELERYD_MAX_TASKS_PER_CHILD = 2 # 每個worker最大執行任務數
# 指定時區,不指定默認爲 'UTC'
CELERY_TIMEZONE = 'Asia/Shanghai'
# 指定導入的任務模塊
CELERY_IMPORTS = (
'celery_app.tasks',
)
重新啓動
執行
celery beat -A celery_app -l info --detach
啓動celery,通過ps -ef | grep celery可以看到兩個celery worker進程(8226,8228)
利用celery worker進行某個任務,當worker沒有執行到最大任務時(即銷燬重建),每執行一次任務佔用內存必然有所增加,任務數爲9,10時(celery均勻調度,併發數*最大任務數),分別有原8228 worker被銷燬,重新創建9386 worker及原8226 worker被銷燬,重新創建9564 worker,此時,運行第9次時,佔用總內存有所下降,運行第10次時,總內存回到初如值,同樣任務執行第19、20次情況類似。
celery併發計算規則
celery任務併發只與celery配置項CELERYD_CONCURRENCY 有關,與CELERYD_MAX_TASKS_PER_CHILD沒有關係,即CELERYD_CONCURRENCY=2,只能併發2個worker,此時任務處理較大的文件時,執行兩次可以看到兩個task任務並行執行,而執行第三個任務時,開始排隊,直到兩個worker執行完畢。
結論
celery執行完任務不釋放內存與原worker一直沒有被銷燬有關,因此CELERYD_MAX_TASKS_PER_CHILD可以適當配置小點,而任務併發數與CELERYD_CONCURRENCY配置項有關,每增加一個worker必然增加內存消耗,同時也影響到一個worker何時被銷燬,因爲celery是均勻調度任務至每個worker,因此也不宜配置過大,適當配置。