1. 程式人生 > >結合Django+celery二次開發定時周期任務

結合Django+celery二次開發定時周期任務

由於 抓取 而是 文檔 code 機會 編輯 越來越大 內存泄漏

需求:

前端時間由於開發新上線一大批系統,上完之後沒有配套的報表系統、監控,於是乎開發、測試、產品、運營、業務部、財務等等各個部門就跟那饑渴的餓狼一樣需要

各種各樣的系統數據滿足他們。剛開始一天一個還能滿足他們,優化腳本之後只要開發提供查詢數據的SQL、收件人、執行時間等等參數就可以幾分鐘寫完一個定時任務腳本

,到後面不知道是不是吃藥了一天三四個定時任務,不到半個月手裏一下就20多個定時任務了,漸漸感到力不從心了,而且天天還要給他們修改定時任務的SQL、收件人、執

行時間等等,天天寫定時任務腳本都寫到想吐,真是心裏面一萬只草泥馬崩騰而過。於是乎下定決心寫一個定時任務管理系統,把所有的定時任務都統一放到一個平臺上進行

管理,經過大半個月的調查發現Django+Celery是一個不錯的方案。Django結合djcelery模塊可以在django-admin管理後臺配置定時任務,但是頁面是寫死的不靈活,所

以只能再二次開發一個頁面進行配置管理。

詳細的安裝步驟不細說,網上有大量文檔,我是參照51cto一位哥們兒安裝的。

celery3.x版本安裝:http://shineforever.blog.51cto.com/1429204/1737323

celery4.x版本安裝:http://www.cnblogs.com/alex3714/p/6351797.html (金角大王)

我選擇的是celery3.x版本的,用的django-celery模塊,celery4.x用的是django-celery-beat,因為celery4.x版本的django-celery-beat在djang-admin後臺添加task後系統不會

對修改後的任務即時生效,而是需要重啟celery-beat服務才能生效,真你妹擦蛋,而且網上一直沒找到解決方案,所以選擇了celery3.x版本,此版本在django-admin後臺增刪改查

task後不用重啟celery-beat就能生效。

django-admin頁面

技術分享

periodic tasks 配置頁面

技術分享

參數配置頁面

技術分享

periodic tasks 列表頁面

技術分享

我的定時任務腳本通常是根據開發給的SQL語句去生產庫裏抓取數據然後生成Excel文件再以郵件形式發給各個部門,因此需要傳的參數有SQL語句(SQL有時十幾個,而且

比屎還長)、每一個SQL執行的數據庫、郵件收件人、郵件抄送人、郵件標題、Excel文件名等等,由於參數太多如果用django-admin裏自帶的頁面進行配置task,那麽就需要在

參數配置頁面裏寫跟屎一樣長的一大串列表或者字典,非常不方便,而且它的列表頁面也不人性化,所以需要一個人性化的頁面進行配置和管理。

django-celery所生成的表

技術分享

經過測試發現在django-admin所做的修改其實都是修改數據庫,修改後django-celery會實時推送到celery-beat裏生效。所以只要再開發一個頁面去配置djcelery_periodictask及

其它表就可以了。

定時任務列表頁面,對應djcelery_periodictask表

技術分享

新增或修改配置定時任務頁面

技術分享

技術分享

crontab執行時間的列表頁面,這個頁面和django-admin一樣,照搬的,這樣就不用再跑到admin頁面去配置。

技術分享

crontab編輯頁面

技術分享

總結:

從技術調研到開發、測試完成折騰了一個多月,這樣統一到一個平臺管理後更加方便快捷,配置、修改一個定時任務分分鐘搞定。celery支持集群,

如果以後任務多了,成百上千的定時任務就可以用celery的集群。

有時候有些定時任務會因為某些原因失敗,所以我還想對執行的任務進行監控,我想知道每天有多少任務執行成功、有多少失敗、耗時多長時間、

如果執行失敗,失敗原因是什麽等等,剛開始用的flower,但是在django項目裏app少的時候可以把flower服務起來,我的項目十多個app硬是沒起來,只好放棄,

而且flower的監控頁面跟django-admin裏的一樣periodic_tasks頁面一樣直接顯示的所有參數值,非常不人性化,還需要二次開發,這樣還是自己寫一個celery的

監控。

我的平臺用的是django,所以可以直接用django-celery,如果平臺是tornado、flask、bottle那又該怎麽結合celery來開發定時任務系統。根據網上一個哥

們兒的分析,原來django-celery是自已定義了一個任務調度器,在django-admin頁面裏配置、修改任務以後如何將這些修改反應到celery-beat裏都是調度器完成

的,也就是這個DatabaseScheduler模塊

from djcelery.schedulers import DatabaseScheduler

settings裏還需要指定任務調度器,很熟悉吧。

CELERYBEAT_SCHEDULER = djcelery.schedulers.DatabaseScheduler # 定時任務調度器

所以,如果要結合tornado、flask、bottle就需要自定義一個調度器,我也很推薦這種方法,奈何自己代碼能力有限,不知如何下手,有機會還是要試試。

哥們兒博客地址:http://www.liuliqiang.info/post/celery-advanced-topic-scheduler-and-priority/,裏面有他自己寫的調度器,大濕(師)啊。

有幾個註意點:

1.時區

剛開始時區不準,一直是UTC時間,後來索性把utc禁用,在settings裏增加配置

CELERY_ENABLE_UTC = False

2.內存泄漏

剛開始我開了10個worker跑定時任務,跑10多個定時任務,才跑兩天就發現woker占的內存越來越大一直不釋放,後來發現默認每個worker跑完100個任務後才會自我

銷毀程序重建來釋放內存,所以需要增加一個配置定義每個worker執行多少個任務後才會自我銷毀重建。

CELERYD_MAX_TASKS_PER_CHILD = 3 #  每個worker最多執行3個任務就會被銷毀,可防止內存泄露

結合Django+celery二次開發定時周期任務