Django-Celery异步的使用
请求过程简单说明:浏览器发起请求-->请求处理-->请求经过中间件-->路由映射-->视图处理业务逻辑-->响应请求(template或response)
1.快速入门
(本文以 Celery4.0 为基础进行书写)
首先,我们要理解 Celery 本身不是任务队列,它是管理分布式任务队列的工具,或者换一种说法,它封装好了操作常见任务队列的各种操作,我们用它可以快速进行任务队列的使用与管理,当然你也可以自己看 rabbitmq 等队列的文档然后自己实现相关操作都是没有问题的。
Celery 是语言无关的,虽然它是用 Python 实现的,但他提供了其他常见语言的接口支持。只是如果你恰好使用 Python 进行开发那么使用 Celery 就自然而然了。
想让 Celery 运行起来我们要明白几个概念:
1.1 Brokers
brokers 中文意思为中间人,在这里就是指任务队列本身,Celery 扮演生产者和消费者的角色,brokers 就是生产者和消费者存放/拿取产品的地方(队列)
常见的 brokers 有 rabbitmq、redis、Zookeeper 等
1.2 Result Stores / backend
顾名思义就是结果储存的地方,队列中的任务运行完后的结果或者状态需要被任务发送者知道,那么就需要一个地方储存这些结果,就是 Result Stores 了
常见的 backend 有 redis、Memcached 甚至常用的数据都可以。
1.3 Workers
就是 Celery 中的工作者,类似与生产/消费模型中的消费者,其从队列中取出任务并执行
1.4 Tasks
就是我们想在队列中进行的任务咯,一般由用户、触发器或其他操作将任务入队,然后交由 workers 进行处理。
理解以上概念后我们就可以快速实现一个队列的操作:
Django使用步骤:
1.安装‘中间人broker’,使用redis作为中间人,还可以使用RabbitMQ
- pip install redis ---->redis版本不能太高不然会和Celery不匹配 - pip install celery - pip install celery-with-redis
2.在settings.py中进行celery的配置
# celery配置 CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0' # Broker配置,使用Redis作为消息中间件 CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/0' # BACKEND配置,这里使用redis存储结果 BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 3600} # 链接超时 # 可以接收的链接格式 CELERY_ACCEPT_JSON = ['application/json', ] # 任务的序列化 CELERY_TASK_SERIALIZER = 'json' # 结果序列化 CELERY_RESULT_SERIALIZER = 'json' # celery时区 TIME_ZONE Django配置的时区 CELERY_TIMEZONE = TIME_ZONE
3.在需要使用异步的app的目录中定义一个叫做task.py的文件
引入装饰器 from celery import @shared_task #邮箱案例 @shared_task def send_email_activate(username, receive, u_token): subject = '%s AXF Activate' % username from_email = EMAIL_HOST_USER recipient_list = [receive, ] data = { 'username': username, 'activate_url': 'http://{}:{}/axf/activate/?u_token={}'.format(SERVER_HOST, SERVER_PORT, u_token) } html_message = loader.get_template('user/activate.html').render(data) send_mail(subject=subject, message="", html_message=html_message, from_email=from_email, recipient_list=recipient_list)
4.启动异步celery
#注册 def register(request): if request.method == "GET": data = { "title": "注册" } return render(request, 'user/register.html', context=data) elif request.method == "POST": username = request.POST.get("username") email = request.POST.get("email") password = request.POST.get("password") icon = request.FILES.get("icon") # password = hash_str(password) password = make_password(password) user = AXFUser() user.u_username = username user.u_password = password user.u_email = email user.u_icon = icon user.save() u_token = uuid.uuid4().hex cache.set(u_token, user.id, timeout=60 * 60 * 24) # 启动异步.delay send_email_activate.delay(username, email, u_token) return redirect(reverse('axf:login'))
5.配置celery作为一个单独的线程,帮助用户异步发送邮件
A: 在项目同名文件夹下新建一个celery.py文件(目的:加载settings.py中配置信息给celery对象) from __future__ import absolute_import, unicode_literals import os from celery import Celery os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gits.settings') # 设置django环境 app = Celery('gits') # 使用CELERY_ 作为前缀,在settings中写配置 app.config_from_object('django.conf:settings', namespace='CELERY') # 发现任务文件每个app下的task.py app.autodiscover_tasks() B:在项目同名文件夹下init.py中添加 from __future__ import absolute_import, unicode_literals ''' absolute_import绝对导入: 如果当前项目由一个sys.py,我用的时候总会调用系统的sys.py。 如果当前目录和sys.path的路径中都有一个foo,则会调用当前目录下的foo。 unicode_literrals: 对字符串使用unicode字符 ''' # 导入刚才配置的celery_app对象 from .celery import app as celery_app __all__ = ['celery_app']
6.测试启动异步
启动异步worker celery beat启动命令: celery -A 项目名 beat -l info Redis服务端启动命令 redis-server