celery佔用大內存-內存泄漏

問題發現

本來top命令查看服務器實時內存情況,  突然發現32G內存 celery 佔用到12%,  內存佔用都快4G了.

  1. top命令下,M鍵開啓按MEM列排序的進程列表,按H則查看線程列表,由於worker沒有子線程,所以只顯示一條記錄;
  2. c命令,開始COMMAND列詳細情況,可以找到對應的進程啓動者;
  3. 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,因此也不宜配置過大,適當配置。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章