Django中使用Celery Solo模式执行串行异步任务
本文介绍如何在Django项目中利用Celery的Solo模式处理耗时且需串行的异步任务。通过配置Redis作为消息代理,并设置worker为solo模式,确保任务按序执行且不并发。文章涵盖环境安装、Celery应用创建、Django集成及日志配置,解决高负载下任务漏执行或并行冲突问题。
Django串行异步任务背景
前言
在Django项目开发中,有时会遇到耗时较长的数据更新(update)流程。为了在后台处理该流程时,Web应用仍能正常响应其他前端请求,同时确保该更新任务必须串行执行(即不能并行处理)且不能遗漏任何请求,我们需要引入异步任务队列机制。
Celery Solo模式配置
使用Celery的Solo模式解决
Redis环境安装
安装Redis
访问Redis官方发布页面:https://github.com/microsoftarchive/redis/releases
下载对应的.msi安装包进行安装。安装过程会自动将Redis注册为Windows系统服务,便于后台运行管理。
依赖库安装与应用创建
安装Celery与Redis依赖
pip install celery
pip indatll redis
创建一个基础的Celery应用实例。
# celery_test.py
import time
from celery import Celery
app = Celery('tasks', broker='redis://127.0.0.1:6379/0')
@app.task
def add(x, y):
time.sleep(5)
return x + y
启动服务与参数详解
启动Celery Worker服务。
celery -A celery_test.app worker --pool=solo -l info
查看完整的命令行参数列表
celery worker --help
对Celery启动命令中关键参数的解释如下:
- '-A' 参数用于指定全局配置,即Celery应用实例的位置。
- '--pool' 参数用于配置Worker的进程池模式。默认值为prefork(支持并发),但在此场景下选择'solo'模式。启用Solo模式后,发送给Worker的任务将不再并发执行;当Worker正在执行某个任务时,后续发送的任务会在队列中排队,只有当前任务执行完毕后,Worker才会开始执行下一个任务。
- '-l' 参数用于配置Worker的日志记录级别。
任务调用与串行效果验证
调用异步任务
>>> from celery_test import add
>>> add.delay(4,4)
由于启用了Solo模式,可以观察到:在第一个add任务尚未执行完毕前,即使再次发送执行add的任务请求,Celery Worker也会等待前一个任务完全结束后,再依次执行后续任务,从而保证了任务的串行性。
Django集成与日志处理
与Django框架结合
在初始化Celery应用之前,必须先调用django.setup()来配置Django环境。
import time
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demo.settings")
django.setup()
from celery import Celery
from django_app.update import update
app = Celery('tasks', broker='redis://127.0.0.1:6379/0', backend='redis://127.0.0.1:6379/0')
@app.task
def update_task():
update()
配置完成后,即可在Django的views视图中直接调用定义好的task。
from celery_test import update_task
def update_api(request):
if request.method == "GET":
update_task.delay()
return HttpResponse(status=status.HTTP_200_OK)
在任务执行过程中,程序中的print输出信息会被记录为Celery的warning级别日志,而报错信息则被记录为error级别日志。
日志路径配置
日志配置
在启动Celery应用时,可以通过参数指定日志文件的保存路径。
-f log_path
如果不设置该参数,日志信息将默认输出到控制台。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









