django使用celery定时任务,使用redis和supervisor。

时间:2022-02-01 20:46:00

前言

在django项目中,使用celery异步执行任务,以及创建定时任务。
使用redis作为中间件,用supervisor管理进程。

django项目代码
http://download.csdn.net/detail/win_turn/9772404

Begin

当前路径

django使用celery定时任务,使用redis和supervisor。

创建虚拟环境

有关virtualenv的讲解,可查看
http://blog.csdn.net/win_turn/article/details/60466451

virtualenv win

django使用celery定时任务,使用redis和supervisor。

进入虚拟环境

source win/bin/activate

django使用celery定时任务,使用redis和supervisor。

安装package

建议先配置一下pip的国内镜像
http://blog.csdn.net/win_turn/article/details/59733715

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使用celery定时任务,使用redis和supervisor。
当前目录结构
django使用celery定时任务,使用redis和supervisor。

配置django

vi pro/settings.py

INSTALLED_APPS中添加新增的app
django使用celery定时任务,使用redis和supervisor。
在文件末尾添加celery配置
django使用celery定时任务,使用redis和supervisor。
CELERYD_LOG_FILE是celery worker的日志文件
CELERYBEAT_LOG_FILE是celery beat的日志文件

2017年3月20日更新
今天进行数据迁移时发现个问题,一直没有celery日志文件。
后来才发现,原来CELERYD_LOG_FILECELERYBEAT_LOG_FILE已经在4.0版本中不再支持了。改用参数-f指定日志文件。

创建celery.py

vi pro/celery.py

django使用celery定时任务,使用redis和supervisor。

修改init.py

为了确保在django启动时加载了celery应用,修改init.py文件

vi pro/__init__.py

django使用celery定时任务,使用redis和supervisor。

当前目录结构
django使用celery定时任务,使用redis和supervisor。

测试celery

在redis服务启动的情况下,测试celery worker已经准备好接收django的任务

关于redis的安装和启动,以及使用supervisor管理redis进程,请参考:
http://blog.csdn.net/win_turn/article/details/60615729

celery worker -A pro -l info

django使用celery定时任务,使用redis和supervisor。

使用Ctrl+c关闭,然后再测试celery beat是否已经准备好。

celery beat -A pro -l info

django使用celery定时任务,使用redis和supervisor。
测试通过,说明django项目已经配置好了celery。

做好django项目的准备工作

接下来,我们在wechat的视图中,简单的写一个业务逻辑,在用户访问时,及时返回给用户。
当前的业务场景是:访问192.168.139.129:7777/money/时,显示用户wangteng的账户余额。
django使用celery定时任务,使用redis和supervisor。

描述待实现功能

希望实现的功能是:
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
django使用celery定时任务,使用redis和supervisor。
在视图views.py中调用tasks.py中的任务时,需要使用task_name.delay(args)的方式。

参考文档

有关第33行代码中crontab的用法:
http://docs.celeryproject.org/en/master/reference/celery.schedules.html#celery.schedules.crontab

如果第35行代码ignore_result=True表示不存储任务状态,意味着你不能使用AsyncResult来检查任务是否就绪,或者获取它的返回值。
http://docs.celeryproject.org/en/latest/userguide/tasks.html#Task.ignore_result
http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-task_ignore_result

使用supervisor

使用supervisor管理celery worker程序。

进程管理工具的介绍,可以参考:
http://blog.csdn.net/win_turn/article/details/60466562

sudo vi /etc/supervisord.conf

django使用celery定时任务,使用redis和supervisor。

注意:上面截图中,对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://guest@localhost//'
--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://guest@localhost//'
--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使用celery定时任务,使用redis和supervisor。

运行django项目

python manage.py runserver 0.0.0.0:7777

django使用celery定时任务,使用redis和supervisor。
在浏览器输入192.168.139.129:7777/money/,浏览器能够立马接收到django返回的数据,并不需要等待。
django使用celery定时任务,使用redis和supervisor。

查看celery日志

查看celery beat和celery worker的日志

celery beat的作用,就是按照规定的时间,将“开始运行任务”的指令发送给celery worker。因此,该日志文件中,记录的是派送任务的时间以及接受任务的任务名称。
django使用celery定时任务,使用redis和supervisor。
celery0.log日志文件中,记录的是celery层面的信息,包括任务的执行时间、结束时间、所用时长、返回值等信息。
django使用celery定时任务,使用redis和supervisor。
celery1.log日志文件中,记录的是task任务过程中的信息,包括运行过程中,时间时间、输出的print和info、任务名称等信息。
这个文件名中的数字1表示第几个worker进程。还记得才supervisord.conf中启动celery worker时的参数-c吗?如果启动worker时,参数-c 3,那么这里将会有celery1.logcelery2.logcelery3.log三个文件。
这个日志文件名的定义,是在settings.py中设置的。
django使用celery定时任务,使用redis和supervisor。

查看redis

在日志中,有一串不规则的字符串,这个是每个任务的id。可以通过这个id,在redis中查询到该任务的信息。

例如查询任务id为1b68e5cb-21e1-4cdc-9cf6-bdbbfe7785b6任务的信息。

redis-cli

django使用celery定时任务,使用redis和supervisor。