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

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

参考文章:https://www.jb51.net/article/158046.htm

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

Celery简单介绍:

celery使用场景:

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

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

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

任务模块 Task

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

消息中间件 Broker

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

任务执行单元 Worker

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

任务结果存储 Backend

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

p>django-celery



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

解决方法:建议降低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 .....人都知道

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

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。

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

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

from celery import Celery, platforms
platforms.C_FORCE_ROOT = True

2.验证celery任务

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

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

(0)

相关推荐

  • Django配置celery(非djcelery)执行异步任务和定时任务

    所有演示均基于Django2.0 celery是一个基于python开发的简单.灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的机器/进程/线程上执行任务调度.采用典型的生产者-消费者模型,主要由三部分组成: 消息队列broker:broker实际上就是一个MQ队列服务,可以使用redis.rabbitmq等作为broker 处理任务的消费者workers:broker通知worker队列中有任务,worker去队列中取出任务执行,每一个worker就是一个进程 存储结果的bac

  • 如何解决django-celery启动后迅速关闭

    日志中也没有打印什么明显的错误,只是显示连接了rabbitmq后就关闭了 [2019-09-11 06:08:45,729: INFO/Beat] beat: Starting... [2019-09-11 06:08:45,731: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672// [2019-09-11 06:08:45,732: INFO/Beat] Writing entries (0)... [2019-09

  • Django使用Celery异步任务队列的使用

    1 Celery简介 Celery是异步任务队列,可以独立于主进程运行,在主进程退出后,也不影响队列中的任务执行. 任务执行异常退出,重新启动后,会继续执行队列中的其他任务,同时可以缓存停止期间接收的工作任务,这个功能依赖于消息队列(MQ.Redis). 1.1 Celery原理 Celery的 架构 由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成. 消息中间件:Celery本身不提供消息服务,但

  • Django中使用celery完成异步任务的示例代码

    本文主要介绍如何在django中用celery完成异步任务,web项目中为了提高用户体验可以对一些耗时操作放到异步队列中去执行,例如激活邮件,后台计算操作等等 当前项目环境为: django==1.11.8 celery==3.1.25 redis==2.10.6 pip==9.0.1 python3==3.5.2 django-celery==3.1.17 一,创建Django项目及celery配置 1,创建Django项目 1>打开终端输入:django-admin startproject

  • 详解django+django-celery+celery的整合实战

    本篇文章主要是由于计划使用django写一个计划任务出来,可以定时的轮换值班人员名称或者定时执行脚本等功能,百度无数坑之后,终于可以凑合把这套东西部署上.本人英文不好,英文好或者希望深入学习或使用的人,建议去参考官方文档,而且本篇的记录不一定正确,仅仅实现crontab 的功能而已. 希望深入学习的人可以参考 http://docs.jinkan.org/docs/celery/ . 首先简单介绍一下,Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其

  • 详解Java中异步转同步的六种方法

    目录 一.问题 应用场景 二.分析 三.实现方法 1.轮询与休眠重试机制 2.wait/notify 3.Lock Condition 4.CountDownLatch 5.CyclicBarrier 6.LockSupport 一.问题 应用场景 应用中通过框架发送异步命令时,不能立刻返回命令的执行结果,而是异步返回命令的执行结果. 那么,问题来了,针对应用中这种异步调用,能不能像同步调用一样立刻获取到命令的执行结果,如何实现异步转同步? 二.分析 首先,解释下同步和异步 同步,就是发出一个调

  • 详解SpringBoot中异步请求和异步调用(看完这一篇就够了)

    一.SpringBoot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如长时间的运算)时再对客户端进行响应.一句话:增加了服务器对客户端请求的吞吐量(实际生产上我们用的比较少,如果并发请求量很大的情况下,我们会通过nginx把请求负载到集群服务的各个节点上来分摊请求压力,当然还可以通过消息队列来做请求的缓冲). 2.异步请求的实现 方式一:Servlet方式实现异步请求

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

    Celery文档参考:http://docs.jinkan.org/docs/celery/ 参考文章:https://www.jb51.net/article/158046.htm Django中异步任务---django-celery Celery简单介绍: celery使用场景: 耗时任务定时任务 请求结果不怎么重要的 耗时任务比如:发送短信验证码我们可以先发送给客户任务状态(请求成功或失败) 请求结果重要的建议使用django实现 比如:支付 首先简单介绍一下,Celery 是一个强大的

  • 详解nodejs中的异步迭代器

    前言 从 Node.jsv10.0.0 开始,异步迭代器就出现中了,最近它们在社区中的吸引力越来越大.在本文中,我们将讨论异步迭代器的作用,还将解决它们可能用于什么目的的问题. 什么是异步迭代器 那么什么是异步迭代器?它们实际上是以前可用的迭代器的异步版本.当我们不知道迭代的值和最终状态时,可以使用异步迭代器,最终我们得到可以解决{value:any,done:boolean}对象的 promise.我们还获得了 for-await-of 循环,以帮助我们循环异步迭代器.就像 for-of 循环

  • 详解Java中CountDownLatch异步转同步工具类

    使用场景 由于公司业务需求,需要对接socket.MQTT等消息队列. 众所周知 socket 是双向通信,socket的回复是人为定义的,客户端推送消息给服务端,服务端的回复是两条线.无法像http请求有回复. 下发指令给硬件时,需要校验此次数据下发是否成功. 用户体验而言,点击按钮就要知道此次的下发成功或失败. 如上图模型, 第一种方案使用Tread.sleep 优点:占用资源小,放弃当前cpu资源 缺点: 回复速度快,休眠时间过长,仍然需要等待休眠结束才能返回,响应速度是固定的,无法及时响

  • 一文详解Python中PO模式的设计与实现

    目录 什么是PO模式 PO 三层模式 PO 设计模式的优点 将改写的脚本转为PO设计模式 构建基础的 BasePage 层 构建首页的 Page 层(HomePage) 构建登录页的 Page 层(LoginPage) 构建 首页 - 订单 - 支付 流程的 Page 层(OrderPage) PO 设计模式下测试Case的改造 在使用 Python 进行编码的时候,会使用自身自带的编码设计格式,比如说最常见的单例模式,稍微抽象一些的抽象工厂模式等等… 在利用 Python 做自动化测试的时候,

  • 一文详解Python中logging模块的用法

    目录 一.低配logging 1.v1 2.v2 3.v3 二.高配logging 1.配置日志文件 2.使用日志 三.Django日志配置文件 一.低配logging 日志总共分为以下五个级别,这个五个级别自下而上进行匹配 debug-->info-->warning-->error-->critical,默认最低级别为warning级别. 1.v1 import logging logging.debug('调试信息') logging.info('正常信息') logging

  • 详解jQuery中ajax.load()方法

    jQuery load() 方法 jQuery load() 方法是简单但强大的 AJAX 方法. load() 方法从服务器加载数据,并把返回的数据放入被选元素中. 语法: $(selector).load(URL,data,callback); load()函数用于从服务器加载数据,并使用返回的html内容替换当前匹配元素的内容. load()函数默认使用GET方式,如果提供了对象形式的数据,则自动转为POST方式. 因为默认使用的是Get请求方式,所以我们也可以在url加数据进行提交. 例

  • 详解Android中图片的三级缓存及实例

    详解Android中图片的三级缓存及实例 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响 特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知 所以提出三级缓存策略,通过网络.本地.内存三级缓存图片,来减少不必要的网络交互,避免浪费流量

  • 详解Android 中AsyncTask 的使用

    详解Android 中AsyncTask 的使用 1.首先我们来看看AsyncTask 的介绍:   Handler 和 AsyncTask 都是android 中用来实现异步任务处理的方式:其中: Handler 实例向 UI 线程发送消息,完成界面更新, 优点:对整个过程控制的比较精细:         缺点:代码相对臃肿,多个任务同时执行时,不易对线程进行精确的控制: AsyncTask :比Handler 更轻量级一些,适用于简单的异步处理: 优点:简单 | 快捷 | 过程可控:    

随机推荐