同步和异步请求概述
在讲celery之前,先说一下同步请求和异步请求
同步请求:所有逻辑处理、数据计算任务在view中处理完毕返回response,在views处理任务时,用户处于等待状态,直到页面返回结果。
异步请求:view中现将结果返回response,再在后台处理任务。用户无需等待,可以继续浏览网站。当任务处理完成时,我们可以再告知用户
为什么会需要消息队列(MQ)?
原因:由于高并发环境下,由于来不及同步处理请求,请求往往会发生阻塞,比如大量的insert,update之类的请求同时到达数据库,直接导致无数的行锁表锁,甚至最后请求堆积过多,从而触发too many connections错误。使用消息队列,可以一步处理请求,从而减轻系统的压力
队列概述
消息队列:是分布式系统中重要的组件
当不需要立即获取结果,但是并发量又需要进行控制的时候,差不多就需要使用消息队列的时候
消息队列主要解决了应用耦合,异步处理,流量削峰等问题:
当前使用的消息队列有:RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,而部分数据库如Redis、Mysql以及phxsql也可实现消息队列的功能。
celery
概述:当视图函数执行某些耗时操作的时候,用户界面则为一直请求(加载)用户体验不好,使用celery进行异步加载
步骤
1.任务:task
2.队列:queue
3.工人:worker
4.broker:负责调度
(1)celery解决的问题
1.耗时的任务执行
2.定时任务
(2)安装
pip install celery
pip install celery-with-redis
pip install django-celery
(3)配置settings
在INSTALLED_APPS添加如下代码
INSTALLED_APPS = [
...
'App',
'djcelery',
]
import djcelery
djcelery.setup_loader() #初始化
BROKER_URL = 'redis://127.0.0.1:6379/0' #进行调度的地址 加载执行的数据库0
CELERY_IMPORTS = ('App.task') #导入装有任务的py文件
(4)创建task.py
from celery import task
@task
def test1():
print('走到当前的任务了')
time.sleep(5)
print(''任务执行完毕'')
(5)生成celery所需的表
python manage.py migrate
(6)在工程目录下创建celery.py(与settings.py同级)
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'whthas_home.settings')
app = Celery('portal')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
(7)在工程init.py文件中添加代码如下(与settings.py同级)
from .celery import app as celery_app
(8)在视图中导入任务
from django.shortcuts import render,HttpResponse
from App.task import test1
def index(req):
if req.method == 'GET':
test1.delay() #将耗时任务放到 队列里 异步加载
return render(req,'index.html')
(9)启动redis
1.redis-server
2.redis-cli
(10)启动worker
python manage.py celery worker --loglevel=info # 详细展示当前的执行信息
二、定时执行一个或多个任务
(1).定时执行一个任务
settings.py添加代码如下:
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
'schedule-test':{
'task':'App.task.test1', #定时执行的任务的函数名称
'schedule':timedelta(seconds=7) #定时执行的间隔时间
}
}
起动顺序
1.启动django
python manage.py runserver
2.启动broker
python manage.py celery broker --loglevel=info
3.启动定时任务
python manange.py celery beat --loglevel=info
(2)定时执行多个任务
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
'schedule-test':{
'task':'App.task.test1', #定时执行的任务的函数名称
'schedule':timedelta(seconds=7) #定时执行的间隔时间
},
'schedule-test2':{
'task':'App.task.test2', #定时执行的任务的函数名称
'schedule':timedelta(seconds=7), #定时执行的间隔时间
'args':(3,) #定时任务传参
}
}
task.py
from celery import task
import time
@task
def test1():
print('走到当前的任务了')
time.sleep(5)
print('任务执行完毕')
@task
def test2(i):
print('打印',i)
time.sleep(5)
print('打印',i)