celery任務調度框架實踐
celery架構圖:
Celery Beat:任務調度器,Beat進程會讀取配置文件的內容,週期性地將配置中到期需要執行的任務發送給任務隊列。
Celery Worker:執行任務的消費者,通常會在多臺服務器運行多個消費者來提高執行效率。
Broker:消息代理,或者叫作消息中間件,接受任務生產者發送過來的任務消息,存進隊列再按序分發給任務消費方(通常是消息隊列或者數據庫)。
Producer:調用了Celery提供的API、函數或者裝飾器而產生任務並交給任務隊列處理的都是任務生產者。
Result Backend:任務處理完後保存狀態信息和結果,以供查詢。Celery默認已支持Redis、RabbitMQ、MongoDB、Django ORM、SQLAlchemy等方式。
初始化:
1.運行celery
mac環境下的celery一下載就能直接運行。
但是centos6.9 環境下好像下載之後並不能直接運行,估計是環境變量沒有配好。
需要加上celery的安裝路徑。
使用/usr/local/bin/celery -A your_app worker --loglevel=info
2.以守護進程運行celery:
需要一個初始化腳本:celeryd
使用方法:/etc/init.d/celeryd {start|stop|restart|status}
配置文件:/etc/default/celeryd
參考:
3.使用redis:
mac下安裝redis
- brew install redis
- 如果需要後臺運行 redis 服務,使用命令 brew services start redis
- 如果不需要後臺服務,則使用命令 redis-server /usr/local/etc/redis.conf。
- mac os 安裝 redis
安裝redis後,啓動時指定配置文件
redis-server ./redis.conf
檢測後臺進程是否存在
ps -ef |grep redis
使用分佈式時,其他worker機子無法訪問redis去取任務:
- redis默認的安全策略,只准許本地訪問。
- 需要通過簡單配置,完成允許外網訪問。
- 參考:開啓redis 允許外網IP 訪問
celery基本操作命令:
參考:
celery worker:
1.啓動worker:
export PYTHONOPTIMIZE=1 && /usr/local/bin/celery -A your_app worker --loglevel=debug --workdir=/your_dir/your_dir/your_dir/
2.停止worker:
ps auxww | grep 'celery worker' | awk '{print $2}' | xargs kill -9
3.在celery中使用多進程:
我用的是from multiprocessing import Pool
來實現多進程。
但是在運行過程中會直接報出這個錯誤
AssertionError: daemonic processes are not allowed to have children
解決方法:
重寫一個Mypool
https://stackoverflow.com/questions/6974695/python-process-pool-non-daemonic
設置環境變量
export PYTHONOPTIMIZE=1
由於過段時間就會失效。。所以每次啓動worker的時候的時候:
export PYTHONOPTIMIZE=1 && /usr/local/bin/celery -A your_app worker --loglevel=debug --workdir=/your_dir/your_dir/your_dir/
以下 的方法沒試過:
there are two method to solve this problem ,disable assert:
1.where celery starts set export PYTHONOPTIMIZE=1 OR start celery with this parameter -O OPTIMIZATION
2.disable python packet multiprocessing process.py line 102:
assert not _current_process._config.get(‘daemon’), \ ‘daemonic processes are not allowed to have children’
4.調用worker、添加任務:
delay()和apply_async()
我們之前調用任務使用了”delay()”方法,它其實是對”apply_async()”方法的封裝,使得你只要傳入任務所需的參數即可。對於特殊的任務調度需求,你需要使用”apply_async()”,其常用的參數有:
- countdown: 指定多少秒後任務才被執行
- eta: 指定任務被調度的時間,參數類型是datetime
- expires: 任務過期時間,參數類型可以是int(秒),也可以是datetime
- retry: 任務發送失敗的重試次數
- priority: 任務優先級,範圍是0-9
- serializer: 參數和返回值的序列化方式
celery beat 定時任務
一個時間的Bug:
- 當前使用pip安裝的celery,默認是安裝的最新版本4.1.0,但是在這個版本中在獲取當前時間的邏輯中存在bug,會導致定時任務配置後並不能在指定的時間被執行
- 回退版本 到4.0.2才行
- celery 4.1.0 版本定時任務執行時間 bug
另一種可行但麻煩的思路:
celery的定時任務會有一定時間的延遲。比如,我規定模擬登陸新浪微博任務每隔10個小時執行一次,那麼定時任務第一次執行就會在開啓定時任務之後的10個小時後纔會執行。而我抓取微博需要馬上執行,需要帶上cookie,所以不能等那1個小時。這個沒有一個比較好的解決方法,可以使用celery的crontab()來代替schdule做定時,它會在啓動的時候就執行。我採用的方法是第一次手動執行該任務,然後再通過schedule執行。
使用命令:
進入到對應your_app對應的目錄下:cd /your_dir/your_dir/your_dir
再執行:/usr/local/bin/celery -A your_app beat -l info
最方便的是,在命令中指定工作目錄,一條命令即可:
/usr/local/bin/celery -A your_dir beat -l info --workdir=/your_dir/your_dir/your_dir/
定時任務參數參考表:
動態管理定時任務:
查過挺多資料,有兩種解決方法。跟celery運行的調度器(schedule)息息相關的。
- 使用第三方schedule:
如django-celery-beat庫會將定時任務的規則存入到數據庫中,而不用通過配置文件來定義。
try to install django-celery instead of django-celery-beat. django-celery works with Celery 3 (unlike django-celery-beat). You can then, for example import PeriodicTask from djcelery.models instead of from django_celery_beat.models . This allows you to add/delete/manipulate tasks both dynamically AND PROGRAMMATICALLY (not only from the Django admin site). The drawback to this workaround is that if one doesn’t need django-celery for anything other than this, then it bloats one’s app. Thus, It would be better to have Celery 4.0 included in cookiecutter-django so that django-celery-beat models can be used
- 使用框架默認schedule
我使用的是這一種方法。
只能管理celery的配置文件了,每次增加或減少定時任務的時候,都要對配置文件進行相應的修改。
每次修改完都要重啓celerybeat,試過多種方法,發現用supervisor來管理celery beat的進程是比較好的。
管理celery beat進程
用supervisor來管理celery beat進程。
安裝:
pip install supervisor
Supervisor配置
/usr/local/bin/echo_supervisord_conf > /etc/supervisord.conf
操作:
- 開啓:
supervisord -c /etc/supervisord.conf
- 重啓:
supervisorctl -c /etc/supervisord.conf reload
- 關閉:
supervisorctl -c /etc/supervisord.conf shutdown
- 開啓:
other:
分佈式:
隊列:
flower:
圖形化管理celery界面:
/usr/local/bin/celery -A celery_app flower --port=5555