celery服务

celery服务

官方

Celery 官网:http://www.celeryproject.org/

Celery 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html

Celery 官方文档中文版:http://docs.jinkan.org/docs/celery/

celery简介

Celery异步任务框架

"""
1)可以不依赖任何服务器,通过自身命令,启动服务(内部支持socket)
2)celery服务为为其他项目服务提供异步解决任务需求的
注:会有两个服务同时运行,一个是项目服务,一个是celery服务,项目服务将需要异步处理的任务交给celery服务,celery就会在需要时异步完成项目的需求

人是一个独立运行的服务 | 医院也是一个独立运行的服务
	正常情况下,人可以完成所有健康情况的动作,不需要医院的参与;但当人生病时,就会被医院接收,解决人生病问题
	人生病的处理方案交给医院来解决,所有人不生病时,医院独立运行,人生病时,医院就来解决人生病的需求
"""

Celery架构

Celery的架构由三部分组成,消息中间件(message broker)、任务执行单元(worker)和 任务执行结果存储(task result store)组成。

image-20230308165106622

  • 消息中间件

    Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等

  • 任务执行单元

    Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。

  • 任务结果存储

    Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等

使用场景

  • 异步执行:解决耗时任务
  • 延迟执行:解决延迟任务
  • 定时执行:解决周期(周期)任务

celery安装配置

pip install celery

celery基本配置方法

消息中间件推荐使用缓存数据库:RabbitMQ/Redis

"""1.配置Celery对象作为app"""
import celery
broker = 'redis://127.0.0.1:6379/1'  # 使用redis的db1存储
backend = 'redis://127.0.0.1:6379/2'  # 使用redis的db2存储
app=Celery('任务名', broker=broker, backend=backend)
# broker存储任务代码(缓存数据库的某一个db)
# backend存储执行结果


"""2.app.task可以装饰在函数上以注册任务"""
@app.task   # 让任务被注册到app中,有delay方法等
def task(*params):
    执行过程
    return 结果

"""3.启动worker执行单位,监听这些被注册的任务"""
win中还需要安装eventlet模块:
-4.x之前版本
celery worker -A main -l info -P eventlet
-4.x之后
celery  -A main  worker -l info -P eventlet

-A 后跟app产生的py文件名
-l  日志等级设置
-P eventlet (win的要求)
## 执行这条语句后,app配置的broker数据库就存入了注册的函数程序

"""4.在某处调用task时,使用delay进行提交,则提交由worker执行,
并将执行的状态或结果存放在app注册的backend数据库中"""
task(*params)  # 正常调用,则为同步调用
task.delay(*params)  # 使用delay调用,则提交任务到broker数据库(还未正式执行)
# 返回一个AsyncResult对象,打印的话显示其id属性

"""5.查看执行结果,可以直接通过delay返回的AsyncResult对象
也可以通过该对象的id值,重新实例化一个AsyncResult对象去查看"""
from main import app
from celery.result import AsyncResult
task_id = '51611be7-4914-4bd2-992d-749008e9c1a6'  # 调用
if __name__ == '__main__':
    a = AsyncResult(id=task_id, app=app)
    a.successful()  # 执行成功与否
    a.get()  # 如果执行成功,执行的结果
    a.failed()  # 执行失败与否
    a.status  # 执行的状态,有PENDING,RETRY,STARTED,SUCCESS等状态

包配置celery

以上基本配置是将Celery对象产生在一个py模块文件中的,所以启动worker的命令是:

celery -A 模块名 worker -l 日志等级 -P eventlet

而如果按照以下包结构配置,则要按包名启worker

celery -A 包名 worker -l 日志等级 -P eventlet

-包名如:celery_task
	- __init__.py
	- celery.py   # 必须命名为celery作为Celery对象文件(利用反射)
    	Celery(broker=broker, backend=backend, include=[
            'celery_task.order_task',  # 相对于包所在的文件夹即worker起始环境
            'celery_task.user_task',  # 会将task文件中所有加装app.task的函数注册
            'celery_task.utils_task',  # 底层通过反射解决了定义顺序冲突
            'out_tasks'
        ])
    - order_task.py  # 不同的task文件可以定义一些不同的异步任务
    - user_task.py
            from .celery import app
            @app.task
            def yyy():...
    - utils_task.py
    - ...
- out_tasks.py   # 包外的任务也可以被注册
        from celery_task.celery import app
        @app.task
        def xxx():...

ps:包外的函数可以被注册为异步任务,意味着我们想将一个函数添加成异步任务时,不必调整目录结构,只要加装app.task装饰器和在celery的app中注册即可

调用异步任务和获取执行结果

即时提交任务

asy = func.delay(func所需参数)
# asy为AsyncResult的对象,对象的独有属性只有id号,其他都是获取结果的方法

延时提交任务

eta指定任务提交的时间

asy = func.apply_async(args=[func所需参数],eta=datetime对象)
# 关于设定datetime对象的时间,可以通过timedelta进行计算,
# 也可以datetime.strptime(cls, date_string, format)根据字符串时间生成

配置定时任务

定时任务需要一个一直提交任务的进程,这个我们可以通过py文件自己写循环简单的实现,但是我们可以通过celery的beat命令按照更丰富的方式设置定时任务和提交任务。

如下在app中配置:

## celery文件
app = Celery(...)  # 产生了app后
# 1.设置时区为东八区
app.conf.timezone="Asia/Shanghai"
app.conf.enable_utc = False  # 取消使用utc时间
# 2.配置beat_schedule
app.conf.beat_schedule = {
    '任务名称': {
        'task': 'celery_task.user_task.send_sms',  # 任务路径
        # 'schedule': timedelta(seconds=3),  # 时刻表可以是时差对象,隔段时间执行一次
        # 'schedule': crontab(hour=8, day_of_week=1),  # 每周一早八点
        'schedule': crontab(hour=9, minute=43),  # 每天9点43
        'args': ('18888888', '6666'),  # 任务所需的参数
        'kwargs':{}  # 还可以传关键字参数
        'relative':True  # 时间会基于最近的时分秒去执行
    },
}

ps:尝试去官网找到让定时任务失效的方法,配置options:{expires:未来的datetime},但是失败了。

启动worker和beat:

celery -A celery_task worker -l info -P eventlet  # 启动worker监听任务

celery -A celery_task beat -l info  # 开启beat定时启动任务

AsyncResult对象

这是任务提交方法delay等给我们的返回值,实际上,它主要是包含了很多的获取结果的方法,而对象特有的属性足够的简单,只有id值。

  • id:数据属性,内存中结果的键
  • get():获取数据的执行结果,如果执行失败则不能使用
  • successful():成功返回true
  • failed():成功返回false
  • status:返回目前任务的执行执行状态

django中使用celery

如果我们想将使用了django模块和一些配置的方法设置为celery的异步任务,那么会遇到这么一个问题:worker的工作环境与django是相互独立的,所以在提交任务时,会遇到缺失配置的各种问题,此时只需要在celery.py中配置django环境即可,因为celery是worker的启动文件。

## celery.py
import os
import celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.dev')
app = Celery(...)
posted @ 2023-03-09 17:19  leethon  阅读(37)  评论(0编辑  收藏  举报