celery介绍,celery和Django的结合实现异步任务_django celery和多进程(2)

  • 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
  • 快速:一个单进程的celery每分钟可处理上百万个任务
  • 灵活: 几乎celery的各个组件都可以被扩展及自定制

Celery基本工作流程图

在这里插入图片描述

  • 用户应用程序讲任务通过celery放入Broker中。
  • 多个worker通过Broker获取任务并执行。
  • worker执行完成后,会把任务的结果、状态等信息返回到Broker中存储,供用户程序读取。

Celery 用消息通信,通常使用中间人(Broker)在客户端和职程间斡旋。这个过程从客户端向队列添加消息开始,之后中间人把消息派送给职程。

Celery模块的基本使用

官方文档:https://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html

要使用Celery需要先安装celery模块,下面的例子使用Python3进行举例。

# 利用pip3命令安装celery模块
pip3 install celery
 
# 测试是否成功安装
[root@namenode ~]# python3
Python 3.6.4 (default, Dec 21 2017, 17:26:43)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import celery      # 没有报错表示模块安装正常
>>>

PS:如果你是编译安装的Python3,执行以上步骤后不一定代表正确安装,还需要在命令行下执行celery命令,如果报错请参考这篇文章:Python3安装Celery模块后执行Celery命令报错

下面的例子使用redis作为消息中间人的角色。
1.创建一个celery application
用来定义任务列表,这里任务文件的名称为tasks.py

from celery import Celery

app = Celery('tasks', broker="redis://127.0.0.1:6379", backend="redis://127.0.0.1:6379")
# task 是当前模块的名称,这个参数是必须的,这样的自动生成
# 中间人的地址
# 结果数据存放地址

@app.task  # 使用celery标识一个任务,多个任务都需要使用该装饰器 
def add(x, y):
    return x + y

其他中间件的用法

# rabbitmq
broker = 'amqp://user:password@ip:5672//'
# redis
broker = 'redis://passwordf@ip:6379/db'

2.运行一个worker

celery -A tasks worker --loglevel=debug
# -A参数表示的是Celery APP的名称,tasks就是APP的名称(应用文件名) 也可使用--app 等价于 -A
# worker表示是一个执行任务角色
# loglevel=info记录日志类型默认是info。

3.发布(调用)任务

from tasks import add
result = add.delay(4, 4)
print('Is task ready: %s' % result.ready())
run_result = result.get(timeout=1)
print('task result: %s' % run_result)

PS:调用任务会返回一个 AsyncResult 实例,可用于检查任务的状态,等待任务完成或获取返回值(如果任务失败,则为异常和回溯)。 但这个功能默认是不开启的,需要设置一个 Celery 的结果后端(配置了backend才会生效)。

PS:通过检查redis的数据也可以查看结果信息
在这里插入图片描述

注意事项:这是我个人遇到的一些问题
版本问题 python3.6+ celery4.1.0+ 这个是可以正确使用的搭配
以下报错建议安装eventlet 安装
Celery ValueError: not enough values to unpack (expected 3, got 0)的解决方案
Python3.5 建议使用protobuf3.0.0.beta2

AsyncResult 实例常用方法
通过获取异步执行对象的返回值来获取Asynz cResult实例对象

from tasks import add
result = add.delay(4, 4)  # 返回一个result对象
run_result = result.get(timeout=1)

  • ready() 方法查看任务是否完成处理
result.ready()  # True/False 对象有两个结果 表示完成/未完成

  • get() 等待任务完成,但这很少使用,因为它把异步调用变成了同步调用
 result.get(timeout=1)  # 不加timeout参数会同步等待
 # timeout 表示超时时间,如果在1秒内没有返回会报异常
 #celery.exceptions.TimeoutError: The operation timed out.
 #倘若任务抛出了一个异常, get() 会重新抛出异常。

  > # 使用 propagate 参数美化 get 抛出的异常信息
     # 程序抛出的异常,get也会打印,使用propagate=False来美化输出 
     >>> result.get(propagate=False)
     >>> NameError("name 'name' is not defined",)
      # 我们在worker中引用了一个位置的变量name,使用propagate后显示的结果更优雅
      #  如果celery没有配置backend,那么执行get方法将会异 

  • traceback 获取原始的回溯信息
  • task_id 获取任务的任务id

项目中使用celery

# ---------------------- celery.py ----------------------
 
from __future__ import absolute_import     # 绝对导入,保证不会覆盖celery模块
 
from celery import Celery
 
 
app = Celery(
    'appcelery',      # 项目名称
    broker='redis://10.0.0.3:6379/0',
    backend='redis://10.0.0.3:6379/1',
    include=['appcelery.tasks']    # 包含的worker配置(注意格式:项目名.任务名)
)
 
app.conf.update(     # 利用conf.update配置其他参数
    result_expires=3600,    # 设置worker返回的结果在redis中保存的时间
)
 
if __name__ == '\_\_main\_\_':
    app.start()
 
 
 
# ---------------------- tasks.py ----------------------
 
from .celery import app    # 导入应用
 
@app.task
def add(x,y):
    return x + y
 
@app.task
def minus(x,y):
    return x - y

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值