Celery安装
celery,分布式异步任务队列
eventlet,并发网络库 gevent 协程库
pip install celery==4.4.7
pip install eventlet==0.26.1
Celery介绍
Celery 是一个 基于python的分布式异步任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景:
- 异步任务:将耗时的操作任务提交给Celery异步执行,比如发送短信/邮件、消息推送、音频处理等等
- 做一个定时任务,比如每天定时执行爬虫爬取指定内容
- 还可以使用celery实现简单的分布式爬虫系统等等
Celery 在执行任务时需要通过一个消息中间件(Broker)来接收和发送任务消息,以及存储任务结果
Celery有以下优点:
- 简单:Celery 易于使用和维护,并且它 不需要配置文件 ,并且配置和使用还是比较简单的
- 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
- 快速:单个 Celery 进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级
- 灵活: Celery 几乎所有部分都可以扩展或单独使用,各个部分可以自定义。
## Celery存储任务结果
- 创建一个laufing.py文件,并创建worker
from celery import Celery
app = Celery("worker2", broker="redis://:laufing@localhost:6379/4", backend="redis://:laufing@localhost:6379/5")
@app.task
def task1(a, b):
print("简单求和")
return a + b
@app.task
def task2(a, b):
print("2-s后求和")
time.sleep(20)
return a + b
- 前台启动worker
# windows 下需要加-P eventlet 或者 -P gevent
#因为celery 4.x 对window支持的不太好
celery -A laufing worker --loglevel=info -P eventlet
#window
celery -A laufing worker -l info -P eventlet
- 发送任务,并获取结果
ipython中测试如下:
from laufing import task1, task2
r1 = task1.delay(3, 5) # 发送任务
r1.result
r2 = task2.delay(4, 7) #发送任务,并立即执行下一行,不会阻塞
r2.result # worker来执行task,返回结果后才可以拿到
分布式的worker:
只需在多个主机上启动该laufing下的worker即可, 每一个worker进程都是并发处理任务
celery异步发送短信
在django项目根目录下创建celery.py以及config.py文件,配置以下内容:
config.py文件:
broker_url='redis://:redis密码@127.0.0.1:6379/5'
result_backend='redis://:redis密码@127.0.0.1:6379/6'
celery.py文件:
from celery import Celery
from django.conf import settings
import os
#配置环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE','p6_306.settings')
#实例化celery对象
app=Celery('cc')
#通过配置文件进行配置
app.config_from_object('p6_306.config')
# 让app自动发现任务函数
app.autodiscover_tasks(settings.INSTALLED_APPS)
在django项目子应用下,创建tasks.py
from p6_306.celery import app
from ronglian_sms_sdk import SmsSDK
import json
accId='8aaf07088185853e01*******'
accToken='8ac934ad5ddf44a4a*********'
appId='8aaf07088185853e018********'
#定义任务函数
@app.task
#AUTH TOKEN: 8ac934ad5ddf44a4a1b********
# ACCOUNT SID:8aaf07088185853e0181********
# AppID(默认):8aaf07088185853e01**********
#定义发送短信的函数
def send_message(sms_code,mobile,expire=5):
"""
:param sms_code: 要发送的验证码
:param mobile: 发送手机号
:param expire: 过期时间
:return:
"""
# 实例化sdk对象
sdk=SmsSDK(accId=accId,accToken=accToken,appId=appId)
#准备数据
tid='1'
datas=('%s'%sms_code,'%s'%expire)
#发送短信
res=sdk.sendMessage(tid=tid,mobile=mobile,datas=datas)
data =json.loads(res)
print('容联云解析的数据:',data)
# if data.get('statusCode')=='000000':
# # return True
# # return False
return data
编写视图类
from rest_framework.views import APIView
from rest_framework.response import Response
import random,redis
from .tasks import send_message
class SmsCodeAPIView(APIView):
#发送短信验证码
def get(self,request):
#获取前端的手机号
mobile=request.query_params.get('mobile')
#生成随机验证码
sms_code=random.randint(10000,99999)
# 发送短信,异步任务
send_message.delay(sms_code, mobile)
redis_conn = redis.Redis(host='localhost', port=6379, password='shayebushi')
key='sms_%s'%mobile
redis_conn.set(key,sms_code,ex=300)
return Response({'code': 200, 'msg': '发送短信,注意查收'})
#启动指令
# celery -A p6_306 worker -l info -P eventlet
# 验证短信验证码
def post(self,request):
#1.获取前端的手机号,验证码
mobile=request.data.get('mobile')
sms_code=request.data.get('smsCode')
# 2.获取存储的验证码
redis_conn=redis.Redis(host='localhost',port=6379,password='shayebushi')
key='sms_%s'%mobile
stored_code=redis_conn.get(key)
#3.判断验证码是否一致
if stored_code and stored_code.decode()==sms_code:
return Response({'code':200,'msg':'验证成功'})
return Response({'code':400,'msg':'验证失败'})
配置路由
from django.urls import path
from users import views
urlpatterns = [
#获取短信验证码
path('sms_code/',views.SmsCodeAPIView.as_view())
]
启动celery
# windows系统下启动
celery -A mdpro worker -l info -P eventlet
# mac下启动,
celery -A mdpro worker -l info