1. celery worker佔用內存情況
併發n個wokers,n如下表1的worker數,在不執行任務的情況下,n個worker對應rss值(/sys/fs/cgroup/memory/memory.stat)及每增加一個worker所增加rss值情況。
worker數 |
RSS值(B) |
RSS增量(MB)[n-(n-1)] |
0 |
364810240 |
|
1 |
407392256 |
40.609 [1-0] |
2 |
434069504 |
25.441 |
3 |
450125824 |
15.313 |
4 |
464175104 |
13.398 |
5 |
482721792 |
17.688 |
6 |
496492544 |
13.132 |
7 |
512901120 |
15.648 |
8 |
529100800 |
15.449 |
9 |
545804288 |
15.930 |
10 |
563519488 |
16.896 |
…… |
…… |
…… |
19 |
707670016 |
|
20 |
726679552 |
18.129 [20-19] |
表1 開啓worker數佔用內存情況
由此可以看出,每增加一個worker對應rss值增加16MB左右
(20workers對應rss值-0 workers對應rss值)/1024/1024/20=17.255MB
2. celery內存泄露分析
celery配置項如下
CELERYD_CONCURRENCY = 2 celery worker併發數
CELERYD_MAX_TASKS_PER_CHILD = 5 每個worker最大執行任務數
執行celery -A ansibleAPI.celery worker啓動celery,通過ps -ef | grep celery可以看到兩個celery worker進程(8226,8228)。
利用celery worker進行備份任務,每次任務執行完畢對應rss值如下表2,從下表可以看出,當worker沒有執行到最大任務時(即銷燬重建),每執行一次任務rss必然有所增加,任務數爲9,10時(celery均勻調度,併發數*最大任務數),分別有原8228 worker被銷燬,重新創建9386 worker及原8226 worker被銷燬,重新創建9564 worker,此時,從表中可以看到運行第9次時,rss有所下降,運行第10次時,rss回到初如值,同樣任務執行第19、20次情況類似。
任務數 |
RSS值(B) |
0 |
437100544 |
1 |
444547072 |
2 |
449728512 |
3 |
449929216 |
4 |
450220032 |
5 |
450392064 |
6 |
450600960 |
7 |
450662400 |
8 |
450711552 |
9 |
440414208 |
10 |
435408896 |
11 |
441864192 |
12 |
451543040 |
13 |
451756032 |
…… |
…… |
19 |
441851904 |
20 |
435810304 |
表2 celery每執行一次任務對應rss值情況
2.celery併發計算規則
celery任務併發只與celery配置項CELERYD_CONCURRENCY 有關,與CELERYD_MAX_TASKS_PER_CHILD沒有關係,即CELERYD_CONCURRENCY=2,只能併發2個worker,此時備份較大的文件,執行兩次可以看到兩個task任務並行執行,而執行第三個任務時,開始排隊,直到兩個worker執行完畢。
4. 結論
celery執行完任務不釋放內存與原worker一直沒有被銷燬有關,因此CELERYD_MAX_TASKS_PER_CHILD可以適當配置小點,而任務併發數與CELERYD_CONCURRENCY配置項有關,每增加一個worker必然增加內存消耗,同時也影響到一個worker何時被銷燬,因爲celery是均勻調度任務至每個worker,因此也不宜配置過大,適當配置。