1. 程式人生 > >django使用celery定時任務,使用redis和supervisor。

django使用celery定時任務,使用redis和supervisor。

前言

在django專案中,使用celery非同步執行任務,以及建立定時任務。
使用redis作為中介軟體,用supervisor管理程序。

Begin

當前路徑

這裡寫圖片描述

建立虛擬環境

virtualenv win

這裡寫圖片描述

進入虛擬環境

source win/bin/activate

這裡寫圖片描述

安裝package

pip install -r requirements.txt
#檔案requirements.txt的內容
amqp==2.1.4
beautifulsoup4==4.5.3
billiard==3.5.0.2
celery==4.0.2
Django
==1.10.6 kombu==4.0.2 lxml==3.7.3 pytz==2016.10 redis==2.10.5 requests==2.13.0 vine==1.1.3

建立django專案和應用

django-admin startproject pro
cd pro/
django-admin startapp wechat

這裡寫圖片描述
當前目錄結構
這裡寫圖片描述

配置django

vi pro/settings.py

INSTALLED_APPS中新增新增的app
這裡寫圖片描述
在檔案末尾新增celery配置
這裡寫圖片描述
CELERYD_LOG_FILE是celery worker的日誌檔案
CELERYBEAT_LOG_FILE

是celery beat的日誌檔案

2017年3月20日更新
今天進行資料遷移時發現個問題,一直沒有celery日誌檔案。
後來才發現,原來CELERYD_LOG_FILECELERYBEAT_LOG_FILE已經在4.0版本中不再支援了。改用引數-f指定日誌檔案。

建立init_celery.py

vi pro/init_celery.py

這裡寫圖片描述

修改init.py

為了確保在django啟動時載入了celery應用,修改init.py檔案

vi pro/__init__.py

2017年10月2日增加
將下圖中第5行的from .celery import … 改為 from .init_celery import …

這裡寫圖片描述

當前目錄結構
這裡寫圖片描述

測試celery

在redis服務啟動的情況下,測試celery worker已經準備好接收django的任務

celery worker -A pro -l info

這裡寫圖片描述

使用Ctrl+c關閉,然後再測試celery beat是否已經準備好。

celery beat -A pro -l info

這裡寫圖片描述
測試通過,說明django專案已經配置好了celery。

做好django專案的準備工作

接下來,我們在wechat的檢視中,簡單的寫一個業務邏輯,在使用者訪問時,及時返回給使用者。
當前的業務場景是:訪問192.168.139.129:7777/money/時,顯示使用者wangteng的賬戶餘額。
這裡寫圖片描述

描述待實現功能

希望實現的功能是:
1:當訪問192.168.139.127:7777/money/後,系統訪問http://www.500.com/pages/info/zhongjiang/網站,獲取一等獎每注獎金金額。10秒鐘後,訪問http://www.500.com/pages/info/zhongjiang/dlt.php,獲取二等獎每注獎金金額。將這兩個數相加,存入資料庫,儲存為使用者wangteng的餘額。(該值沒有任何實際意義,只是想建立一個很費時的任務。)
2:每兩分鐘,列印一次當前時間(模擬定時任務)

建立tasks.py

先在wechat下建立檔案tasks.py,實現該功能。
vi wechat/tasks.py
這裡寫圖片描述
在檢視views.py中呼叫tasks.py中的任務時,需要使用task_name.delay(args)的方式。

參考文件

使用supervisor

使用supervisor管理celery worker程式。

sudo vi /etc/supervisord.conf

這裡寫圖片描述

注意:上面截圖中,對redis的設定有誤。

command=/etc/redis/redis_init_script start
不可以使用上面這種方式啟動redis程序,用這種方式,supervisor監控的是指令碼redis_init_script,而不是redis

應該使用下面這個命令啟動redis
command=/usr/local/bin/redis-server /etc/redis/6379.conf

啟動celery worker時的引數說明

Options:
  -A APP, --app=APP     app instance to use (e.g. module.attr_name)
  -b BROKER, --broker=BROKER
                        url to broker.  default is 'amqp://[email protected]//'
  --loader=LOADER       name of custom loader class to use.
  --config=CONFIG       Name of the configuration module
  --workdir=WORKING_DIRECTORY
                        Optional directory to change to after detaching.
  -C, --no-color        
  -q, --quiet           
  -c CONCURRENCY, --concurrency=CONCURRENCY #worker的程序數,預設是CPU數量
                        Number of child processes processing the queue. The
                        default is the number of CPUs available on your
                        system.
  -P POOL_CLS, --pool=POOL_CLS
                        Pool implementation: prefork (default), eventlet,
                        gevent, solo or threads.
  --purge, --discard    Purges all waiting tasks before the daemon is started.
                        **WARNING**: This is unrecoverable, and the tasks will
                        be deleted from the messaging server.
  -l LOGLEVEL, --loglevel=LOGLEVEL
                        Logging level, choose between DEBUG, INFO, WARNING,
                        ERROR, CRITICAL, or FATAL.
  -n HOSTNAME, --hostname=HOSTNAME
                        Set custom hostname, e.g. 'w1.%h'. Expands: %h
                        (hostname), %n (name) and %d, (domain).
  -B, --beat            Also run the celery beat periodic task scheduler.
                        Please note that there must only be one instance of
                        this service.
  -s SCHEDULE_FILENAME, --schedule=SCHEDULE_FILENAME
                        Path to the schedule database if running with the -B
                        option. Defaults to celerybeat-schedule. The extension
                        ".db" may be appended to the filename. Apply
                        optimization profile.  Supported: default, fair
  --scheduler=SCHEDULER_CLS
                        Scheduler class to use. Default is
                        celery.beat.PersistentScheduler
  -S STATE_DB, --statedb=STATE_DB
                        Path to the state database. The extension '.db' may be
                        appended to the filename. Default: None
  -E, --events          Send events that can be captured by monitors like
                        celery events, celerymon, and others.
  --time-limit=TASK_TIME_LIMIT
                        Enables a hard time limit (in seconds int/float) for
                        tasks.
  --soft-time-limit=TASK_SOFT_TIME_LIMIT
                        Enables a soft time limit (in seconds int/float) for
                        tasks.
  --maxtasksperchild=MAX_TASKS_PER_CHILD
                        Maximum number of tasks a pool worker can execute
                        before it's terminated and replaced by a new worker.
  -Q QUEUES, --queues=QUEUES
                        List of queues to enable for this worker, separated by
                        comma. By default all configured queues are enabled.
                        Example: -Q video,image
  -X EXCLUDE_QUEUES, --exclude-queues=EXCLUDE_QUEUES
  -I INCLUDE, --include=INCLUDE
                        Comma separated list of additional modules to import.
                        Example: -I foo.tasks,bar.tasks
  --autoscale=AUTOSCALE
                        Enable autoscaling by providing max_concurrency,
                        min_concurrency. Example:: --autoscale=10,3 (always
                        keep 3 processes, but grow to 10 if necessary)
  --autoreload          Enable autoreloading.
  --no-execv            Don't do execv after multiprocessing child fork.
  --without-gossip      Do not subscribe to other workers events.
  --without-mingle      Do not synchronize with other workers at startup.
  --without-heartbeat   Do not send event heartbeats.
  --heartbeat-interval=HEARTBEAT_INTERVAL
                        Interval in seconds at which to send worker heartbeat
  -O OPTIMIZATION       
  -D, --detach          
  -f LOGFILE, --logfile=LOGFILE
                        Path to log file. If no logfile is specified, stderr
                        is used.
  --pidfile=PIDFILE     Optional file used to store the process pid. The
                        program will not start if this file already exists and
                        the pid is still alive.
  --uid=UID             User id, or user name of the user to run as after
                        detaching.
  --gid=GID             Group id, or group name of the main group to change to
                        after detaching.
  --umask=UMASK         Effective umask (in octal) of the process after
                        detaching.  Inherits the umask of the parent process
                        by default.
  --executable=EXECUTABLE
                        Executable to use for the detached process.
  --version             show program's version number and exit
  -h, --help            show this help message and exit

啟動celerybeat時的引數說明

在檢視這個說明的時候,才發現celerybeat已經不建議使用了。應該使用celery beat(中間有個空格)

Usage: celery beat [options] 

Start the beat periodic task scheduler.

Examples::

    celery beat -l info
    celery beat -s /var/run/celery/beat-schedule --detach
    celery beat -S djcelery.schedulers.DatabaseScheduler


Options:
  -A APP, --app=APP     app instance to use (e.g. module.attr_name)
  -b BROKER, --broker=BROKER
                        url to broker.  default is 'amqp://[email protected]//'
  --loader=LOADER       name of custom loader class to use.
  --config=CONFIG       Name of the configuration module
  --workdir=WORKING_DIRECTORY
                        Optional directory to change to after detaching.
  -C, --no-color        
  -q, --quiet           
  --detach              
  -s SCHEDULE, --schedule=SCHEDULE
  --max-interval=MAX_INTERVAL
  -S SCHEDULER_CLS, --scheduler=SCHEDULER_CLS
  -l LOGLEVEL, --loglevel=LOGLEVEL
  -f LOGFILE, --logfile=LOGFILE
                        Path to log file. If no logfile is specified, stderr
                        is used.
  --pidfile=PIDFILE     Optional file used to store the process pid. The
                        program will not start if this file already exists and
                        the pid is still alive.
  --uid=UID             User id, or user name of the user to run as after
                        detaching.
  --gid=GID             Group id, or group name of the main group to change to
                        after detaching.
  --umask=UMASK         Effective umask (in octal) of the process after
                        detaching.  Inherits the umask of the parent process
                        by default.
  --executable=EXECUTABLE
                        Executable to use for the detached process.
  --version             show program's version number and exit
  -h, --help            show this help message and exit

建立日誌檔案

這兩個日誌檔案,是supervisor的在執行命令期間,螢幕輸出的日誌。並非celery worker和celery beat的日誌。

touch /var/log/supervisor/procelery.log /var/log/supervisor/procelerybeat.log

重啟supervisor

sudo supervisorctl update

這裡寫圖片描述

執行django專案

python manage.py runserver 0.0.0.0:7777

這裡寫圖片描述
在瀏覽器輸入192.168.139.129:7777/money/,瀏覽器能夠立馬接收到django返回的資料,並不需要等待。
這裡寫圖片描述

檢視celery日誌

檢視celery beat和celery worker的日誌

celery beat的作用,就是按照規定的時間,將“開始執行任務”的指令傳送給celery worker。因此,該日誌檔案中,記錄的是派送任務的時間以及接受任務的任務名稱。
這裡寫圖片描述
celery0.log日誌檔案中,記錄的是celery層面的資訊,包括任務的執行時間、結束時間、所用時長、返回值等資訊。
這裡寫圖片描述
celery1.log日誌檔案中,記錄的是task任務過程中的資訊,包括執行過程中,時間時間、輸出的print和info、任務名稱等資訊。
這個檔名中的數字1表示第幾個worker程序。還記得才supervisord.conf中啟動celery worker時的引數-c嗎?如果啟動worker時,引數-c 3,那麼這裡將會有celery1.logcelery2.logcelery3.log三個檔案。
這個日誌檔名的定義,是在settings.py中設定的。
這裡寫圖片描述

檢視redis

在日誌中,有一串不規則的字串,這個是每個任務的id。可以通過這個id,在redis中查詢到該任務的資訊。

例如查詢任務id為1b68e5cb-21e1-4cdc-9cf6-bdbbfe7785b6任務的資訊。

redis-cli

這裡寫圖片描述