一、项目存在的问题:
假如,当前请求发送短信的服务区负载较大,或者网络状况不好,服务器进入等待状态,停止提供其他服务,由于上述问题,开发者迫切需要在发出短信指令后,服务器还可以继续提供其他服务的能力
异步任务:当任务被发起,不会阻塞主线程,会到另外的线程或者进程当中运行,知道结束,返回结果
1、需要解决的思路
首先服务器接收到发送短信的请求
然后服务器将这个任务存放到任务队列中
然后其他服务器领取任务,开始执行
2、开发者可以自己编写上述的需求:
(1)首先定义存放任务和存放返回数据的队列
queue队列,代码级的生产者和消费者,通常用于线程间的数据通信
redis,noSQL数据库,但是可以使用内存进行数据存储,存储高效,适合当做一些快速,高效需求的容器
rabbitmiq专业的开源的小写队列
(2)然后当有任务触发,将任务下发到队列中
(3)其他服务器或者进程轮询检查任务队列,一旦发现任务,立刻执行
二、Django的Celery
1、python的三方也编写了类似的产品:Celery

user 用户
borker 任务容器
workers执行任务的角色
store 保存结果的容器
2、python的Celery框架,是一个专门用来处理异步任务的框架。
celery最常用的两种任务容器和结果容器:
(1)Redis,onSQL数据库,Redis被频繁的使用在并发,分布式当中,Redis可以将数据存在内存当中,运算快。
(2)RabbitMQ消息队列,是一个成熟的用于任务存储和转发的消息队列
3、安装Celery
Django将Celery进行了封装(di-celery),只需要下载注册,配置就可以使用
(1)安装redis

(2)安装django-celery
pip install django-celery==3.2.2
(3)安装python-redis
pip install redis==2.10.6 # 可能出现兼容问题
4、启动redis
在解压Redis文件中
redis-server.exe redis.windows.conf

访问redis,关闭redis
redis-cli.exe
shutdown
4、Celery异步任务
1、安装djcelery到INSTALL_APPS当中

2、创建存放任务的APP
activate Django37
python manage.py startapp CeleryTask
3、在setting中编写Celery代码
#celery
import djcelery
djcelery.setup_loader() #重新加载celery
BROKER_URL = "redis://127.0.0.1:6379/1" #任务存放的容器
CELERY_IMPORTS =("CeleryTask.task") #任务清单
CELERY_TIMEZONE = "Asia/Shanghai" #时区,用于定时任务
CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler" #核心调度器
3、主目录中创建celery文件
添加配置信息
import os
from celery import Celery
from django.conf import settings
#设置celery的环境变量和django-celery的工作目录
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CeleryTask.settings")
#实例化celery应用
app = Celery("our_project")
#加载celery配置
app.config_from_object("django.conf:settings")
#如果项目当中有task.py,那么celery使用app当中的task来生成任务
app.autodiscover_tasks(lambda :settings.INSTALLED_APPS)
4、APP中task文件,编写功能函数
from __future__ import absolute_import #绝对导入
from Qshop.celery import app
from ronglian_sms_sdk import SmsSDK
from Qshop.settings import accId,accToken,appId,tid
@app.task
def say_hi():
print("hi man")
@app.task
def say_hello(number):
print("你好,这是第{}次执行".format(number))
@app.task
def send_message(code,mobile = '13331153360',timer="5"):
sdk = SmsSDK(accId, accToken, appId)
datas = (code, timer)
resp = sdk.sendMessage(tid, mobile, datas)
print(resp)
5、启动Celery
第一次启动需要进行数据迁移
python manage.py check
python manage.py makemigrations
python manage.py migrate
启动celery
python manage.py celery worker --loglevel=INFO
6、修改源码
(1)python3.7将async这个单词定义为关键词,所以不能作为模块名称,需要我们对源码修改

(2)跟据步骤跳转修改变量名称,使用全局修改
asynchronous
7、启动功能函数内的函数,发布任务,可开启多个服务器
python manage.py celery worker --loglevel=INFO
8、使用多服务器可实现发送短信,发送邮件,不影响其他服务器工作
Celery定时任务
例如:电商业务,比如每月的15日,通知会员进行秒杀活动,
通常我们使用LInux的crontab计划任务,可以完成大部分的事情,但是使用调用crontab不是很方便,Celery也推出了自己的定时任务管理
添加定时任务配置
在setting中添加配置
#celery定时任务
from celery.schedules import timedelta,crontab
CELERYBEAT_SCHEDULE = {
u"测试01": {
"task": "CeleryTask.task.say_hi", #任务
"schedule": timedelta(seconds = 2) #计时,没2秒执行一次
}
}
启动worker
python manage.py chelery worker --loglevel=INFO
启动定时任务
python manage.py celery beat --loglevel=INFO