Django使用celery小記

基礎環境

python 3.7
amqp 2.6.0
celery 4.4.3
Django 2.2
flower 0.9.4
可選使用djcelery,這裏我使用的原生celery

celery簡介及應用場景

Celery是基於Python開發的一個分佈式任務隊列框架,採用生產者-消費者模式,主要由三部分組成:broker(消息隊列)、workers(消費者:處理任務)、backend(存儲結果)
主要應用場景:
1、異步任務(async task) 針對請求執行的任務時間較長的情況
2、定時任務(crontab)

1.用戶發起請求接口
2.接口將任務發送到broker隊列
3.celery worker 監控 broker隊列任務並處理
4.celery worker 將結果存儲到backend
在這裏插入圖片描述
從圖上可以看出Celery包含幾個模塊:

任務模塊 Task (生產者)
包括異步任務和定時任務,異步任務通常在業務邏輯中被觸發併發送到任務隊列中,而定時任務是由Celery Beat進程週期性的將任務發往任務隊列。

消息中間件 Broker (中間人)
Broker就是任務調度隊列,接受任務生產者發送來的消息,將任務存入隊列,之所以需要中間人的原因是Celrey本身是不提供消息隊列的服務,所以需要第三方組件實現,常用的有RabbitMQ、Redis。

任務執行單元Worker (消費者)
Worker是執行任務的單元,它實時監控消息隊列,如果有任務就獲取任務並執行它。

任務存儲Backend(存儲結果)
Backend用於存儲任務的執行結果,存儲可以使用RabbitMQ或者Redis或者數據庫等。

異步任務

目錄結構
mysite/mysite是項目配置
mysite/ola_utils是新建的app

mysite
├── README.MD
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── __pycache__
│   ├── celery.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── ola_utils
    ├── __init__.py
    ├── __pycache__
    ├── admin.py
    ├── apps.py
    ├── migrations
    ├── models.py
    ├── tasks.py
    ├── tests.py
    └── views.py

celery主配置文件

'''
mysite/mysite/celery.py
'''
# -*- coding: utf-8 -*-
# @Time    : 2020/6/8 5:03 PM
# @Author  : zhangzd
# @Email   : [email protected]
# @File    : celery.py
# @Software: PyCharm
from __future__ import absolute_import, unicode_literals

import os

from celery import Celery, platforms

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')

app = Celery('mysite', backend='amqp', broker='amqp://guest:guest@localhost:5672')

# 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', namespace='CELERY')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()


# 允許root 用戶運行celery
platforms.C_FORCE_ROOT = True

# 防止內存泄漏,限制worker執行任務次數
app.conf.worker_max_tasks_per_child = 40

@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

# 定時任務
from celery.schedules import crontab

app.conf.update(
    CELERYBEAT_SCHEDULE={
        'send-report': {
            # 具體需要執行的函數
            # 該函數必須要使用@shared_task裝飾
            'task': 'ola_utils.tasks.report',
            # 定時時間
            # 每分鐘執行一次,不能爲小數
            'schedule': crontab(minute='*/1'),
            # 或者這麼寫,每小時執行一次
            # "schedule": crontab(minute=0, hour="*/1")
            # 執行的函數需要的參數
            'args': ()
        }
    }
)

在mysite/init.py文件中增加如下內容,確保django啓動的時候這個app能夠被加載到

'''
mysite/mysite/__init__.py
'''

from __future__ import absolute_import, unicode_literals

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

__all__ = ('celery_app',)

注意tasks.py必須建在各app的根目錄下,且只能叫tasks.py,不能隨意命名

'''
mysite/ola_utils/tasks.py
'''
from __future__ import absolute_import, unicode_literals

from celery import shared_task

import time



@shared_task
def add(x, y):
    time.sleep(10)
    return x + y

在視圖文件內調用視圖函數觸發異步任務

'''
mysite/ola_utils/views.py
'''
from django.shortcuts import render

# Create your views here.
import time
from django.http import HttpResponse

from ola_utils.tasks import add

def heartbeat(request):
    t = time.time()
    try:
        # r = test.delay()
        r = add.delay(2,6)
        print(r)
    except Exception as e:
        print(e)
    return HttpResponse(t)

啓動celery worker
celery -A mysite worker -l info

定時任務

# 定時任務配置
from celery.schedules import crontab

app.conf.update(
    CELERYBEAT_SCHEDULE={
        'send-report': {
            # 具體需要執行的函數
            # 該函數必須要使用@shared_task裝飾
            'task': 'ola_utils.tasks.report',
            # 定時時間
            # 每分鐘執行一次,不能爲小數
            'schedule': crontab(minute='*/1'),
            # 或者這麼寫,每小時執行一次
            # "schedule": crontab(minute=0, hour="*/1")
            # 執行的函數需要的參數
            'args': ()
        }
    }
)
'''
mysite/ola_utils/tasks.py
'''

@shared_task
def report():
    print(5)
    return 5

同時執行異步任務和定時任務
celery -B -A mysite worker -l info

結果
在這裏插入圖片描述

其他

celery 官網:https://docs.celeryproject.org/en/4.4.3/django/first-steps-with-django.html
celery 配置參數
https://docs.celeryproject.org/en/master/userguide/configuration.html?highlight=CELERYD_MAX_TASKS_PER_CHILD#std:setting-worker_max_tasks_per_child

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章