详解Django中异步任务之django-celery


Posted in Python onNovember 05, 2020

Celery文档参考:http://docs.jinkan.org/docs/celery/

参考文章:https://3water.com/article/158046.htm

Django中异步任务---django-celery

Celery简单介绍:

celery使用场景:

  1. 耗时任务定时任务
  2. 请求结果不怎么重要的
  • 耗时任务比如:发送短信验证码我们可以先发送给客户任务状态(请求成功或失败)
  • 请求结果重要的建议使用django实现 比如:支付

首先简单介绍一下,Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务(asynctask)和定时任务(crontab)。它的架构组成如下图

详解Django中异步任务之django-celery

Celery 主要包含以下几个模块:

任务模块 Task

包含异步任务和定时任务。其中,异步任务通常在业务逻辑中被触发并发往任务队列,而定时任务由 Celery Beat 进程周期性地将任务发往任务队列。

消息中间件 Broker

Broker,即为任务调度队列,接收任务生产者发来的消息(即任务),将任务存入队列。Celery 本身不提供队列服务,官方推荐使用 RabbitMQ 和 Redis 等。

任务执行单元 Worker

Worker 是执行任务的处理单元,它实时监控消息队列,获取队列中调度的任务,并执行它。

任务结果存储 Backend

Backend 用于存储任务的执行结果,以供查询。同消息中间件一样,存储也可使用 RabbitMQ, Redis 和 MongoDB 等。

p>django-celery


首先需要统一一下使用的环境,以为如果redis的版本过高会报错

详解Django中异步任务之django-celery

解决方法:建议降低redis版本

推荐版本

Django == 2.2.6

django-celery == 3.3.1

django-redis == 4.11.0

redis == 2.10.6

celery == 3.1.26.post2

依赖安装:pip install .....详解Django中异步任务之django-celery人都知道

1.修改setting.py django配置文件,增加如下:

import djcelery ###导包
djcelery.setup_loader() ###
BROKER_URL = 'redis://127.0.0.1:6379/2'
# BROKER_URL='redis://192.168.217.77:16379/2' #任何可用的redis都可以,不一定要在django server运行的主机上
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' ### 
INSTALLED_APPS = [
 ...
 "djcelery",	# 加入djcelery应用
 ...
 
]
CELERY_TIMEZONE='Asia/Shanghai' #并没有北京时区,与下面TIME_ZONE应该一致
TIME_ZONE='Asia/Shanghai' #

开头增加如上配置文件,根据实际情况配置redis的地址和端口,时区一定要设置为Asia/Shanghai。否则时间不准确回影响定时任务的运行。

上面代码首先导出djcelery模块,并调用setup_loader方法加载有关配置;注意配置时区,不然默认使用UTC时间会比东八区慢8个小时。其中INSTALLED_APPS末尾添加两项,分别表示添加celery服务和自己定义的apps服务。

2.创建Celery所需的数据表

python manage.py migrate
#如若不成功可以尝试一下命令语句
#python manage.py syncdb

3.创建task

详解Django中异步任务之django-celery

stasks.py

# -*- coding: utf-8 -*-
import json, time
from syl.settings import ALY_ACCESSKEY_ID, ALY_ACCESSKEY_SECRET
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
from celery import task
 
 
# 阿里云短信验证码
 
@task
def Celery_Send_Sms(phone, data):
 client = AcsClient(ALY_ACCESSKEY_ID, ALY_ACCESSKEY_SECRET, 'cn-hangzhou')
 request = CommonRequest()
 request.set_accept_format('json')
 request.set_domain('dysmsapi.aliyuncs.com')
 request.set_method('POST')
 request.set_protocol_type('https') # https | http
 request.set_version('2017-05-25')
 request.set_action_name('SendSms')
 request.add_query_param('RegionId', "cn-hangzhou")
 request.add_query_param('PhoneNumbers', phone)
 request.add_query_param('SignName', "美多商城")
 request.add_query_param('TemplateCode', "SMS_205397849")
 request.add_query_param('TemplateParam', data)
 response = client.do_action(request)
 time.sleep(10)
 print(str(response, encoding='utf-8'))
 res = json.loads(str(response, encoding='utf-8'))
 
#celery运行命令
# python manage.py celery worker --loglevel=info
  1. settings.py中的djcelery.setup_loader()运行时, Celery便会查看所有INSTALLED_APPS中app目录中的tasks.py文件, 找到标记为task的function, 并将它们注册为celery task.
  2. 在执行djcelery.setup_loader()时, task是以INSTALLED_APPS中的app名, 加.tasks.function_name注册的
  3. 一次需要注意 在impprt task时, 需要保持一致
  4. 如果我们由于python path不同而使用不同的引用方式时(例如在tasks.py中使用from myproject.myapp.tasks import add形式), Celery将无法得知这是同一task, 因此可能会引起奇怪的bug。

让任务变成异步

例如我们希望在用户发出request后异步执行该task, 马上返回response, 从而不阻塞该request, 使用户有一个流畅的访问过程. 那么, 我们可以使用.delay。

详解Django中异步任务之django-celery

views.py

import re
import random
from rest_framework.permissions import AllowAny
from django_redis import get_redis_connection
from rest_framework.views import APIView
from rest_framework.response import Response
# from utils.MyBaseView import send_message, Send_Sms
from verifications.stasks import Celery_Send_Sms
 
# 用户注册短信验证码
class SmsCodeView(APIView):
 '''使用apiview的限流'''
 # 1. 所有人可以访问
 permission_classes = (AllowAny,)
 
 def post(self, request):
  # 1. 获取参数
  phone = request.data.get('phone') # 手机号
  image_code = request.data.get('image_code') # 字符串验证码
  image_code_uuid = request.data.get('image_code_uuid') # 前端生成的uuid,是redis中图片验证码的key
 
  # 2. 检查参数
  if not all([phone, image_code, image_code_uuid]):
   return Response({'code': 400, 'msg': '参数不全'})
 
  # 检查手机号是否正确
  if not re.match(r'^1[3456789]\d{9}$', phone):
   return Response({"code": 999, "msg": "手机号码不正确"})
 
  # 3. 检查是否发送
  redis_client = get_redis_connection('img_code') # 连接redis数据库
  # phone_exists = redis_client.get(phone)
  # if phone_exists:
  #  return Response({"code": 999, "msg": "频繁发送, 请稍后再试"})
 
  # 4.检查图片验证码是否合法
  redis_image_code = redis_client.get(image_code_uuid) # 字符串验证码
  if redis_image_code:
   # bytes 转成 string
   redis_image_code = redis_image_code.decode() # 把uuid解码
 
  # 比较用户提供的图片内容是否和redis中保存的一致
  if image_code.upper() != redis_image_code:
   return Response({'code': 999, 'msg': '图片验证码不正确'})
  # 5. 发送
  code = '%06d' % random.randint(100000, 999999) # 随机6位验证码
  print('code===============================================', code)
  # 使用容联云短信验证码
  # send_resp = send_message(phone, (code, "5"))
 
  # 使用阿里云短信验证码
  data = {'code': code}
  # send_resp = Send_Sms(phone, data)
  # 使用celery异步发送短信
  Celery_Send_Sms.delay(phone, data) #delay是注册为celery异步任务的关键点
  # Celery_Send_Sms(phone, data) # delay是注册为celery异步任务的关键点
 
  # 5.1 保存code 到 redis中
  redis_client.setex(phone, 60 * 5, code) # phone:code, 5分钟有效期
  # 5.2 从redis中删除这个图片验证码, 以防再次被使用
  redis_client.delete(image_code_uuid)
 
  # 6.存储这个已经发送验证码的手机号,防止频繁发送(使用pipeline 批量操作 )
  pl = redis_client.pipeline()
  pl.setex(phone, 60 * 5, code)
  pl.delete(image_code_uuid)
  pl.execute()
  # 7. 返回结果
  return Response({"code": 200, "msg": "短信发送成功"})

1.启动celery

首先正常启动你的django任务,然后启动celery服务即可。

python manage.py celery worker --loglevel=info

详解Django中异步任务之django-celery

出现上图这个报错不让超级管理员来启动,在settings.py加入以下配置

from celery import Celery, platforms
platforms.C_FORCE_ROOT = True

2.验证celery任务

在搞定上面的东西以后,你就可以通过postman来请求接口让接口使用celery来异步执行任务而不阻塞你的request请求。

详解Django中异步任务之django-celery

到此这篇关于详解Django中异步任务之django-celery的文章就介绍到这了,更多相关Django异步任务内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python中使用strip()方法删除字符串中空格的教程
May 20 Python
Python脚本获取操作系统版本信息
Dec 17 Python
python 读取目录下csv文件并绘制曲线v111的方法
Jul 06 Python
win7 x64系统中安装Scrapy的方法
Nov 18 Python
解决python中无法自动补全代码的问题
Dec 04 Python
python使用knn实现特征向量分类
Dec 26 Python
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
May 13 Python
利用pandas合并多个excel的方法示例
Oct 10 Python
Python进程池Pool应用实例分析
Nov 27 Python
40个你可能不知道的Python技巧附代码
Jan 29 Python
Python爬虫爬取糗事百科段子实例分享
Jul 31 Python
Python实现天气查询软件
Jun 07 Python
Python Django路径配置实现过程解析
Nov 05 #Python
Python基于tkinter canvas实现图片裁剪功能
Nov 05 #Python
Python利用matplotlib绘制散点图的新手教程
Nov 05 #Python
Python如何利用Har文件进行遍历指定字典替换提交的数据详解
Nov 05 #Python
Python word文本自动化操作实现方法解析
Nov 05 #Python
Python自动化办公Excel模块openpyxl原理及用法解析
Nov 05 #Python
Python中用xlwt制作表格实例讲解
Nov 05 #Python
You might like
一些常用的php简单命令代码集锦
2007/09/24 PHP
php实现用于计算执行时间的类实例
2015/04/18 PHP
PHP SPL标准库之接口(Interface)详解
2015/05/11 PHP
常见PHP数据库解决方案分析介绍
2015/09/24 PHP
PhpStorm本地断点调试的方法步骤
2018/05/21 PHP
基于jquery的button默认enter事件(回车事件)。
2011/05/18 Javascript
js为数字添加逗号并格式化数字的代码
2013/08/23 Javascript
通过$(this)使用jQuery包装后的方法或属性
2014/05/18 Javascript
我的Node.js学习之路(二)NPM模块管理
2014/07/06 Javascript
基于js与flash实现的网站flv视频播放插件代码
2014/10/14 Javascript
JavaScript数组对象实现增加一个返回随机元素的方法
2015/07/27 Javascript
jQuery UI库中dialog对话框功能使用全解析
2016/04/23 Javascript
详解前端构建工具gulpjs的使用介绍及技巧
2017/01/19 Javascript
基于代数方程库Algebra.js解二元一次方程功能示例
2017/06/09 Javascript
jqueryUI tab标签页代码分享
2017/10/09 jQuery
jQuery实现鼠标点击处心形漂浮的炫酷效果示例
2018/04/12 jQuery
JS基于对象的链表实现与使用方法示例
2019/01/31 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
Vue列表循环从指定下标开始的多种解决方案
2020/04/08 Javascript
Vue-router中hash模式与history模式的区别详解
2020/12/15 Vue.js
[01:25]2014DOTA2国际邀请赛 zhou分析LGD比赛情况
2014/07/14 DOTA
[01:02:10]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第一局
2016/02/26 DOTA
python网络编程实例简析
2014/09/26 Python
详解Python中的循环语句的用法
2015/04/09 Python
Python实现控制台输入密码的方法
2015/05/29 Python
pytorch下大型数据集(大型图片)的导入方式
2020/01/08 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
2020/01/09 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
Python库安装速度过慢解决方案
2020/07/14 Python
用python制作个视频下载器
2021/02/01 Python
维也纳通行证:Vienna PASS
2019/07/18 全球购物
长青弘远的面试题
2012/06/09 面试题
行政人员工作职责
2013/12/05 职场文书
幼儿园大班区域活动总结
2014/07/09 职场文书
请病假条范文
2015/08/17 职场文书
靠谱准确的求职信
2019/04/02 职场文书