Django中使用Celery异步及定时任务(附赠代码)

一、简介

Celery是由Python开发、简单、灵活、可靠的分布式任务队列,其本质是生产者消费者模型,生产者发送任务到消息队列,消费者负责处理任务。Celery侧重于实时操作,但对调度支持也很好,其每天可以处理数以百万计的任务。特点:

简单:熟悉celery的工作流程后,配置使用简单
高可用:当任务执行失败或执行过程中发生连接中断,celery会自动尝试重新执行任务
快速:一个单进程的celery每分钟可处理上百万个任务
灵活:几乎celery的各个组件都可以被扩展及自定制
应用场景举例:

1.web应用:当用户在网站进行某个操作需要很长时间完成时,我们可以将这种操作交给Celery执行,直接返回给用户,等到Celery执行完成以后通知用户,大大提好网站的并发以及用户的体验感。

2.任务场景:比如在运维场景下需要批量在几百台机器执行某些命令或者任务,此时Celery可以轻松搞定。

3.定时任务:向定时导数据报表、定时发送通知类似场景,虽然Linux的计划任务可以帮我实现,但是非常不利于管理,而Celery可以提供管理接口和丰富的API。

二、架构&工作原理

Celery由以下三部分构成:消息中间件(Broker)、任务执行单元Worker、结果存储(Backend),如下图:
  在这里插入图片描述
  工作原理:

任务模块Task包含异步任务和定时任务。其中,异步任务通常在业务逻辑中被触发并发往消息队列,而定时任务由Celery Beat进程周期性地将任务发往消息队列;
任务执行单元Worker实时监视消息队列获取队列中的任务执行;
Woker执行完任务后将结果保存在Backend中;
消息中间件Broker
  消息中间件Broker官方提供了很多备选方案,支持RabbitMQ、Redis、Amazon SQS、MongoDB、Memcached 等,官方推荐RabbitMQ。

任务执行单元Worker
  Worker是任务执行单元,负责从消息队列中取出任务执行,它可以启动一个或者多个,也可以启动在不同的机器节点,这就是其实现分布式的核心。

结果存储Backend
  Backend结果存储官方也提供了诸多的存储方式支持:RabbitMQ、 Redis、Memcached,SQLAlchemy, Django ORM、Apache Cassandra、Elasticsearch。

celery.py
此文件跟settings文件同级

# 将代码里的runyi,改成自己的项目名
import os

from celery import Celery
from celery.utils.log import get_task_logger
from celery.schedules import crontab


# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'runyi.settings')

app = Celery('runyi')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()


# 定时任务调度
app.conf.beat_schedule = {
    "every-midnight-check-account-lock": { # 当晚24点整,将所有锁定的账户解锁
        'task': 'get_has_account_lock',
        'schedule': crontab(minute=0, hour=0),
        'args': ()
    }
}



@app.task(bind=True)
def debug_task(self):
    print(f'Request: {self.request!r}')

settings文件的配置

# Celery settings
# 本地连接有可能会导致celery连接错误,将CELERY_BROKER_URL和CELERY_RESULT_BACKEND,加入到本地环境变量,值为:'redis://localhost'
# 经济人
CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://:'+ REDIS_PASSWORD + '@127.0.0.1' + ':' + REDIS_PORT+ '/' +REDIS_DB)
# 存储结果后端
CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://:'+ REDIS_PASSWORD + '@127.0.0.1' + ':' + REDIS_PORT+ '/' +REDIS_DB)
# 时区
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERY_TASK_SERIALIZER = 'json'

各个子应用下如果需要异步任务,创建task.py文件
task.py

import logging
import time
from celery import shared_task
# from management.aliyun.utils import bytes_to_oss

# 如果logging.getLogger()加上子应用,日志会生成2行一模一样的
logger = logging.getLogger()


#测试celery异步
@shared_task
def test_celery(str):
    logger.info('当前已经进入到celery中')
    time.sleep(5)
    logger.info('传递过来的值为:%s'%str)
    logger.info('从celery中出来了')

# 定时任务
@shared_task(name="get_has_account_lock")
def get_has_account_lock():
    # 将所有由于输入密码或验证码次数过多锁定的账户解锁
    logger.info("get_has_account_lock starting...")
    UserInfo.objects.filter(account_lock=0).update(account_lock=1)
    logger.info("get_has_account_lock end...")

在views.py文件中调用

class Test_token(APIView):
    def get(self,request):
		mes = {'code':200}
        test_celery.apply_async(args=['hello,celery'])
        return Response(mes)

在managy.py同级开启终端
启动命令:

# 如果在windows上启动的话,去掉&
celery -A runyi worker -l INFO &
celery -A runyi beat -l INFO &

# 启动并将日志指定到某个文件中
celery -A runyi worker -l INFO --logfile=./logs/celeryWork.log &
celery -A runyi beat -l INFO --logfile=./logs/celeryBeat.log &


注意事项

如果修改了task.py文件的代码,但是运行的时候不起作用, 很简单,重新启动celery work
,这样celery才能识别到task里面的代码被更改了

还有一种情况: task.py里面,一个异步的方法,调用了某个工具函数, 这时如果修改此工具函数, 也必须重新启动celery work

定时任务官网文献:https://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值