Django使用celery完成异步任务

5 篇文章 0 订阅
1 篇文章 0 订阅

参考文档:http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html

中文参考文档:https://www.celerycn.io/ru-men/celery-chu-ci-shi-yong

Celery是一个强大的分布式任务队列,他可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。通常用来实现异步任务和定时任务。异步任务比如发送邮件,文件上传图像处理等;定时任务就是需要在特定时间执行的任务。
任务队列一般用于线程或计算机之间分配工作的一种机制。
任务队列的输入是一个称为任务的工作单元,有专门的工作进行不断的监视任务队列,进行执行新的任务工作。
Celery 通过消息机制进行通信,通常使用中间人(Broker)作为客户端和职程(Worker)调节。启动一个任务,客户端向消息队列发送一条消息,然后中间人(Broker)将消息传递给一个职程(Worker),最后由职程(Worker)进行执行中间人(Broker)分配的任务。
在这里插入图片描述

在Windows下安装如下环境:

celery==4.3.0
Django==2.1.8
django-redis==4.10.0
redis==3.3.8
eventlet==0.25.1
PyMySQL==0.9.3

用Redis当Broker: app.conf.broker_url = 'redis://localhost:6379/0'
用Redis当Backend: app.conf.result_backend = 'redis://127.0.0.1:6379/1'

如果redis有设置登录密码:则格式如下:
‘redis://:password@hostname:port/db_number’

在Django中创建一个项目名为testcelery的项目。

testcelery/__init__.py

from __future__ import absolute_import, unicode_literals

import pymysql
pymysql.install_as_MySQLdb()


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

testcelery/celery.py

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

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

app = Celery('testcelery')
app.conf.broker_url = 'redis://127.0.0.1:6379/0'
app.conf.result_backend = 'redis://127.0.0.1:6379/1'



# 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()


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

app/tasks.py

from __future__ import absolute_import, unicode_literals
# from celery import app
from uuid import uuid4

from app.models import Result
from testcelery.celery import app


@app.task
def add(x, y):
    # 处理完毕存数据库
    Result.objects.create(
        uuid=uuid4().hex,
        result=x+y
    )
    return x + y


@app.task
def mul(x, y):
    return x * y


@app.task
def xsum(numbers):
    return sum(numbers)

默认的并发数为当前计算机的 CPU 数

测试

1、本步骤非必须,只是为了测试看可否正常使用redis。
进入django的后台命令模式:
python manage.py shell

逐条输入以下命令:

>>> from django.core.cache import cache
>>> cache.set('a', '444')
True
>>> cache.has_key('a')
True
>>> cache.get('a')
'444'

2、进入django的后台命令模式:
python manage.py shell

>>> from app.tasks import *
>>> add(1, 3)
4

测试异步

>>> res = add.delay(2, 3)
>>> res.status
'PENDING'

此时返回的结果是“PENDING”,应为没有启动Celery

打开另一个终端,如果是Windows输入下面的命令启动Celery:

celery -A testcelery worker --loglevel=info -P eventlet

如果不是Windows则,输入:
celery -A testcelery worker --loglevel=info

启动界面如下:

 -------------- celery@PC-201401010008 v4.3.0 (rhubarb)
---- **** -----
--- * ***  * -- Windows-7-6.1.7601-SP1 2019-09-08 23:09:22
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app:         testcelery:0x34b95d0
- ** ---------- .> transport:   redis://127.0.0.1:6379/0
- ** ---------- .> results:     redis://127.0.0.1:6379/1
- *** --- * --- .> concurrency: 4 (eventlet)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery


[tasks]
  . app.tasks.add
  . app.tasks.mul
  . app.tasks.xsum
  . testcelery.celery.debug_task

[2019-09-08 23:09:23,016: INFO/MainProcess] Connected to redis://127.0.0.1:6379/0
[2019-09-08 23:09:23,028: INFO/MainProcess] mingle: searching for neighbors
[2019-09-08 23:09:24,053: INFO/MainProcess] mingle: all alone
[2019-09-08 23:09:24,060: WARNING/MainProcess] h:\env\dj218\lib\site-packages\celery\fixups\django.py:202: UserWarning: Using settings.DEBUG leads to a memory leak, nev
er use this setting in production environments!
  warnings.warn('Using settings.DEBUG leads to a memory leak, never '

此时

>>> res.status
'SUCCESS'
>>> res.result
5

定时任务

配置文件中配置定时任务:
在celery.py 文件中配置:

app.conf.beat_schedule = {
    'add-every-30-seconds': {
        'task': 'app.tasks.add',
        'schedule': 2,  # 每2秒执行一次
        'args': (3, 4)
    },
}

启动Celery的worker
celery -A testcelery worker -l info -P eventlet
再启动定时任务:
celery -A testcelery beat

注意:文件名为celery.py 和导入包名from celery import Celery有冲突,则需要把celery.py文件名更改。
涉及两个个地方:
1、项目文件下的__init__.py文件里
from .celeryconfig import app as celery_app

2、tasks.py文件里:
from 项目名.celeryconfig import app

任务失败重试

4.0 版本的新功能

@app.task(autoretry_for=(ReadTimeout,), retry_kwargs={'max_retries': 3, 'countdown': 5})
def test_func():
    viewutils.test_func()

@app.task装饰器中的参数:
autoretry_for:
异常类的列表或元组,如果任务在执行的过程中引发异常,任务将自动重试。默认情况下不会自动重试任何异常。
retry_kwargs:
字典类型,自定义配置自动重试参数。注意,如果使用下面的 exponential backoff 选项,countdown 任务选项将由 Celery 的自动重试系统决定,字典中包含 countdown 会被忽略。
retry_backoff:
一个布尔值或一个数字。如果将此选项设置为True,则自动重试将按照 exponential backoff 规则延迟。第一次重试延迟 1 秒,第二次重试延迟 2 秒,第三次延迟 4 秒,第四次延迟 8 秒,以此类推。(如果启用了 retry_jitter 会修改延迟值)。如果该选项设置为数字,则作为延迟因子,例如,该选项设置为 3,那么第一次重试将延迟 3 秒,第二次将延迟 6 秒,第三次延迟 12 秒,第四次延迟 24秒,以此类推。默认情况下,该选项设置为 False,自动重试不会延迟。
retry_backoff_max:
一个数字,如果启动了 retry_backoff,该选项在任务自动重试之间设置以秒为单位的最大延迟。默认情况,该选项默认值为 600,即 10分钟。

autoretry_for
exc:指定抛出的异常
throw:重试时是否通知worker是重试任务
eta:指定重试的时间/日期
countdown:在多久之后重试(每多少秒重试一次)
max_retries:最大重试次数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要通过CeleryDjango中启用异步类视图,您需要执行以下步骤: 1. 首先,确保已经安装了CeleryDjango-Celery包。您可以使用以下命令来安装它们: ``` pip install celery django-celery ``` 2. 在Django项目的settings.py文件中,添加以下配置: ```python # Celery配置 CELERY_BROKER_URL = 'redis://localhost:6379' CELERY_RESULT_BACKEND = 'redis://localhost:6379' ``` 这里使用了Redis作为消息代理和结果后端,您可以根据需要选择其他选项。 3. 创建一个名为`tasks.py`的文件,并在其中定义您的Celery任务。例如: ```python from celery import shared_task @shared_task def your_async_task(*args, **kwargs): # 执行异步任务的代码逻辑 pass ``` 4. 在您的类视图中,使用`@method_decorator`装饰器将`@shared_task`应用于您要异步执行的方法。例如: ```python from django.utils.decorators import method_decorator from yourapp.tasks import your_async_task class YourAsyncView(View): @method_decorator(your_async_task.delay) def post(self, request, *args, **kwargs): # 执行您的视图逻辑 pass ``` 这样,每当您调用此类视图的POST方法时,它将在后台异步执行`your_async_task`任务。 5. 启动Celery工作进程。在终端中,导航到您的项目目录并运行以下命令: ``` celery -A yourprojectname worker --loglevel=info ``` 这将启动一个Celery工作进程,准备接收和执行异步任务。 现在,当您访问包含上述类视图的URL并发送POST请求时,该请求将被异步处理,而不会阻塞主线程。请确保您的Celery工作进程正在运行,并根据需要进行其他配置和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值