一. 目的
批量做接口請求時谐岁,運行時長超過1min擒抛,前端不可能一直等待結(jié)果蔬充,因此考慮異步處理的方式
二. 處理方式
使用celery框架
三. 介紹
celery是一個使用python編寫的簡單羽莺、實用的分布式任務框架灭袁,采用典型的生產(chǎn)者-消費者模式猬错,主要由三部分組成:broker(消息隊列)、workers(消費者:處理任務)茸歧、backend(存儲結(jié)果)倦炒。broker消息隊列負責發(fā)送和接收消息,celery本身不提供消息服務软瞎,但celery官網(wǎng)給出了多個broker的備選方案:RabbitMQ逢唤、Redis、Database(不推薦)以及其他的消息中間件铜涉;workers任務執(zhí)行單元智玻,可在一臺或者多臺機器中同時開啟多個worker進程分布式地并發(fā)處理任務遂唧;backend結(jié)果存儲位置芙代,Django項目中,若未定義,默認存儲在數(shù)據(jù)庫中诫咱,倘若對任務執(zhí)行過程【未執(zhí)行谤逼、執(zhí)行中等狀態(tài)】比較重視的話究抓,需要考慮一下
四. 版本選擇
一種方式使用Django-celery
庫玖姑,另一方式直接使用celery 4.0
版本
由于項目使用的是redis 2.0版本斧拍,這里選用celery 3.0版本井濒,原因:celery 4.0版本對redis版本有要求婉弹,必須3.0版本以上片挂;而celery 3.0 依賴于djcelery幻林,因此直接執(zhí)行pip install djcelery
,下載已包括了celery 3.1.26.post2,無無需單獨下載celery庫
五. 應用
編寫待執(zhí)行的任務,我這里是放在需要執(zhí)行任務的app目錄下音念,文件tasks.py
from celery import task
@task
def manual_request_task(args): # task標記任務
pass
不過我并沒有用Django的Celery實例沪饺,而是自己初始化的實例,見下面的celery.py文件闷愤,調(diào)用實例的task標記函數(shù)如下
from 項目名稱.celery import app # 涉及隱私整葡,用中文名代替匿了
@app.task
def manual_request_task(args):
其他地方調(diào)用異步執(zhí)行任務【這里是views.py】
from APP名稱.tasks import manual_request_task # 中文匿了
manual_request_task.delay(req) # delay() 異步執(zhí)行任務
創(chuàng)建Celery 實例,文件名:celery.py,放置與settings.py同目錄的地方
from __future__ import absolute_import, unicode_literals
import os
from django.conf import settings
from celery import Celery, platforms
platforms.C_FORCE_ROOT = True # 為了能讓supervisor運行celery的worker進程設(shè)置,否則運行權(quán)限不夠讥脐,同時也要考慮安全
# set the default Django settings module for the 'celery' program.目的:讓celery實例能找到Django項目及配置信息
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '項目名稱.settings') # 中文代替匿了
# 實例化對象
app = Celery('項目名稱') # 中文代替匿了
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings') # 4.0 版本后才有的參數(shù)namespace='CELERY'遭居,4.0 要求的redis 是3.2.0及以上
# Load task modules from all registered Django app configs.不需要手動把一個個模塊加到 CELERY_IMPORTS 配置中
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) # 自動發(fā)現(xiàn)項目中各app下的tasks任務
settings.py增加相關(guān)配置
BROKER_URL = 'redis://:****' # 4.0的celery 前綴需要CELERY_
CELERY_RESULT_BACKEND = 'redis://:****'
CELERY_TASK_SERIALIZER = 'pickle' # 4.0版本需要配置,這里未配置
CELERY_RESULT_SERIALIZER = 'pickle' # 4.0版本需要配置旬渠,這里未配置
啟動worker
celery -A 項目 worker --loglevel=info # 我這里使用-A 后的參數(shù)是項目俱萍,不具體指定tasks
到這里基本介紹完celery在Django中異步執(zhí)行任務的功能,定時任務暫時無需求坟漱,略
六. 問題處理
- 報錯
raise AppRegistryNotReady("Apps aren't loaded yet.")
,worker啟動參數(shù)問題 - 報錯
TypeError: 'Settings' object is not subscriptable
,celery版本問題鼠次,更新適合的celery版本