celery分布式异步框架(celery的简单使用,celery多任务结构,celery定时任务,celery计划任务,celery在django项目中使用)

前言基础:
同步
提交一个任务,必须等待任务执行结果才能接着提交任务。
异步
调教任务后,将任务交由后台的其他执行任务的进程或者线程来处理,用户可以继续提交任务,并且任务处理完调用回调函数讲任务提交结果返回。

分布式
一个任务拆开分为多部,交到不同的计算机执行,极大的提高了执行效率,因为多台计算机的处理性能较高

为什么使用CELERY而不使用线程发送耗时任务。
主要是因为并发比较大的时候,线程切换会有开销时间,假如使用线程池会限制并发的数量;同时多线程间的数据共享维护比较麻烦。 而celery是异步任务处理,是分布式的任务队列。它可以让任务的执行同主程序完全脱离,甚至不在同一台主机内。它通过队列来调度任务,不用担心并发量高时系统负载过大。它可以用来处理复杂系统性能问题,却又相当灵活易用。

celery简介
Celery是一个强大的分布式任务队列的异步处理框架,它可以让任务的执行完全脱离主程序,甚至可以分配到其他主机上去(分布式:一个任务分几段,分配到不同主机)运行,我们通常使用异步(async task)和定时任务(crontab).
celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker),任务执行单元(worker),任务执行结果存储(task result store)组成。
消息中间件与结果存储都可以用redis数据库。
在这里插入图片描述
从上图可以看到,Celery主要有几个模块:
任务模块Task
包含异步任务与定时任务。异步任务一般在执行耗时的IO操作任务(首先返回一个调提交的任务号给用户,等处理结束发送处理结束的信号给用户,用户凭借任务号取数据),定时任务Celery Beat进程周期性的讲任务发往任务队列,如数据库每天凌晨更新同步数据。
消息中间件Broker
Broker,即为任务调度队列,接受任务生产者发送过来的消息(操作任务),将用户提交的任务或者操作入队列,Celery本身不提供队列的服务,因此需要第三方的,如redis,以及RabbitMq等个人推荐redis,速度较快
任务执行单元Worker
worker是执行任务的处理单元,它实时监控消息队列,从队列中调度获取任务,并执行。
任务执行结果存储Backend
Backend用于存储任务执行结果,以提供查询使用,它也可以使用RabbitMQ,redis
小结:celery处理大量消息的分布式系统,能处理异步定时任务,使用一般用于处理耗时操作的多任务或者定时性的任务;

celery安装与使用:
pycharm安装celery
pip3 install celery

**简单使用:创建python项目
1实例化出一个对象,并将任务绑定给Celery(@app.task):

from celery import Celery
import time
# broker = broker = "redis://127.0.0.1:6379/1"
# # broker = "redis://:密码@127.0.0.1:6379/1"
broker = "redis://127.0.0.1:6379/1"
backend = "redis://127.0.0.1:6379/1"
# 实例化一个celery对象,传入消息中间件,消息存储队列,然后传入数据处理结果数据库
#celery1为实例化的celery对象的名字,因为可以有多个celery。
app = Celery("celery1",broker=broker,backend=backend)

#通过该装饰器,使得该任务与celery建立绑定关系
@app.task
def multi(x,y):
    time.sleep(1)
    return x*y

2.将装饰的任务函数提交到消息队列中,此时提交的任务函数并没有执行,只是放在消息队列中,等待worker的执行,一旦提交到worker(delay等函数),它将返回一个标识任务的字符串,你可以通过该字符串取出任务执行后的结果:

from testCelery import app,multi

# 调用 任务类对象的return self.apply_async(args, kwargs)
#提交任务delay中为传入的参数,如
res = multi.delay(8,8)
print(res)
#结果标识打印码:
# 74c0b735-afb0-4ceb-a5cb-2d7f9f0d0172

3.使用命令启动worker去执行刚刚调教的任务::

linux下:celery worker -A testCelery -l info
windows下:celery worker -A testCelery -l info -P eventlet

4.查询结果:

from celery.result import AsyncResult
from testCelery import app
ret = AsyncResult(id="74c0b735-afb0-4ceb-a5cb-2d7f9f0d0172",app=app)
if ret.successful():
    res = ret.get()
    print(res)
    print(ret.result)

在这里插入图片描述
Celery的简单使用流程:

安装:
	pip3 install celery
	写一个py文件:testCelery 
	1.指定broker(消息中间件),指定backend(结果存储)
	2.实例化一个celery对象传参:name,broker,backend ;app = Celery("celery1",broker=broker,backend=backend)
	3.加装饰器绑定任务,在函数(add)上加装饰器app.task
	4. 其他程序提交任务,先导入add,add.delay(参,参数),会将该函数提交到消息中间件,但是并不会执行,有个返回值,直接print会打印出任务的id,以后用id去查询任务是否执行完成
   5 启动worker去执行任务:
        linux: celery worker -A celery_task_s1 -l info   
        windows下:celery worker -A celery_task_s1 -l info -P eventlet
  6 查看结果:根据id去查询
            async = AsyncResult(id="74c0b735-afb0-4ceb-a5cb-2d7f9f0d0172", app=app)
            if async.successful():
                #取出它return的值
                result = async.get()
                print(result)

celery的多任务

celery的多任务结构

-项目结构:
pro_cel
├── celery_task# celery相关文件夹
│ ├── celery.py # celery连接和配置相关文件,必须叫这个名字
│ └── tasks1.py # 所有任务函数
│ └── tasks2.py # 所有任务函数
├── check_result.py # 检查结果
└── send_task.py # 触发任务
-启动worker,celery_task是包的名字
celery worker -A celery_task -l info -P eventlet

注意celery.py这个文件的文件名是固定的,不能改,task_1和task_2可以自己定义,他俩代表自定义的任务分类,还可以再创建task_3。。。等其它名字的任务文件,send_task.py是提交任务到worker,check_result.py是查看结果的,注实例化时用到关键字include

#celery.py
from celery import Celery

broker = "redis://127.0.0.1:6379/1"
backend = "redis://127.0.0.1:6379/1"
app = Celery("c2",broker=broker,backend=backend,include=[
    "celery_task.task_1",
    "celery_task.task_2"
])

# celery提供一些配置,具体可查看官方文档
# app.conf.timezone = 'Asia/Shanghai'


task_1.py,task_2.py

task_1.py
from celery_task import celery

@celery.app.task
def add1_task(x,y):
    import time
    time.sleep(1)
    return x+y
task_2.py   
from celery_task import celery

@celery.app.task
def add2_task(x,y):
    import time
    time.sleep(1)
    return x+y

celery的定时任务(类似于linux中的crontab)
方式一:执行时间在某年的某月某时某分某秒:
send_task.py

from celery_task.task_1 import add1_task
from celery_task.task_2 import add2_task


# 启动worker,celery_task是包的名字
# celery worker -A celery_task -l info -P eventlet
#注celery_task为包名
from datetime import datetime
 设置任务执行时间2019年7月14日12点59分58秒
v1 = datetime(2019,7,14,12,59,58)
print(v1)
#将v1时间转换为utc时间
v2 = datetime.utcfromtimestamp(v1.timestamp())
print(v2)

result1 = add1_task.apply_async(args=[6,6],eta=v2)
result2 = add2_task.apply_async(args=[6,6],eta=v2)

print(result1.id)
print(result2.id)

方式二通过延时执行的时间算出执行的具体utc时间
celery的计划任务**

from celery_task.task_1 import add1_task
from celery_task.task_2 import add2_task

# res1 = add1_task.delay(8,8)
# res2 = add2_task.delay(8,8)
# print(res1)
# print(res2)
# 启动worker,celery_task是包的名字
# celery worker -A celery_task -l info -P eventlet
#注celery_task为包名
from datetime import datetime
v1 = datetime(2019,7,14,12,59,58)
print(v1)
v2 = datetime.utcfromtimestamp(v1.timestamp())
print(v2)

from datetime import timedelta
# 使用timedelta模块,拿到10秒后的时间对象,这里参数可以传秒、毫秒、微秒、分、小时、周、天
time_delay = timedelta(seconds=10)
# 得到任务运行时间:
task_time = v2 + time_delay

result1 = add1_task.apply_async(args=[6,6],eta=task_time)
result2 = add2_task.apply_async(args=[6,6],eta=task_time)

print(result1.id)
print(result2.id)

celery计划任务

计划任务需要在celery.py中添加代码,然后需要beat一下,才能将计划开启

from celery import Celery

broker = "redis://127.0.0.1:6379/1"
backend = "redis://127.0.0.1:6379/1"
app = Celery("c2",broker=broker,backend=backend,include=[
    "celery_task.task_1",
    "celery_task.task_2"
])

# celery提供一些配置,具体可查看官方文档
# app.conf.timezone = 'Asia/Shanghai'

from datetime import timedelta
from celery.schedules import crontab

app.conf.beat_schedule = {
    'submit_every_4_seconds':{
        "task":"celery_task.task_1.add1_task",
        "schedule":timedelta(seconds=2),
        "args":[2,8]
    },
    'submit_every_8_seconds': {
        "task": "celery_task.task_1.add2_task",
        "schedule": crontab(minute=55,hour=8,month_of_year=8,day_of_month=2,),
        "args": [2, 8]
    }
}
# 上面写完后,需要起一个进程,启动计划任务
# celery beat -A celery_task -l info

# 启动worker:
# celery worker -A celery_task -l info -P eventlet

Django中使用celery

django-celery:由于djang-celery模块对版本的要求过于严格,而且容易出现很多bug,所以不建议使用

直接使用celery多任务结构的,将celery多任务结构的代码文件夹celery_task拷贝到Django项目中,然后在视图函数中进行任务提交、然后进行结构查看。(启动项目时候记得将worker启动起来,注意启动路径要跟你拷贝的celery_task文件同级)
注意:当我们在Django项目中使用celery,在celery的任务函数中不能直接调用django的环境(比如orm方法查询数据库),需要添加代码调用Django环境

在Python脚本中调用Django环境

import os
# 加载Django环境,bbs是所在的Django项目名称
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'bbs.settings')
    # 引入Django模块
    import django
    # 初始化Django环境
    django.setup()
    # 从app当中导入models
    from app01 import models
    # 调用操作,拿到数据库中的所有Book数据对象
    books = models.Books.objects.all()
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Celery是一个Python分布式任务队列,它可以帮助我们异步执行任务,而且还可以定时执行任务。下面是使用DjangoCelery框架来实现定时任务执行的步骤: 1. 安装Celery。可以使用pip工具来安装Celery。 ```bash pip install celery ``` 2. 配置Django项目。在Django项目的settings.py文件加入以下配置: ```python INSTALLED_APPS = [ # ... 'django_celery_results', 'django_celery_beat', # ... ] CELERY_BROKER_URL = 'redis://localhost:6379' CELERY_RESULT_BACKEND = 'django-db' CELERY_ACCEPT_CONTENT = ['application/json'] CELERY_RESULT_SERIALIZER = 'json' CELERY_TASK_SERIALIZER = 'json' ``` 其CELERY_BROKER_URL是指定Celery使用Redis作为消息代理,CELERY_RESULT_BACKEND是指定Celery的结果存储方式为Django数据库,CELERY_ACCEPT_CONTENT、CELERY_RESULT_SERIALIZER和CELERY_TASK_SERIALIZER则是指定消息的序列化方式。 3. 创建定时任务。在Django项目的tasks.py文件定义需要定时执行任务。例如: ```python from celery import shared_task @shared_task def hello(): print('Hello, World!') ``` 4. 配置定时任务。在Django项目的settings.py文件加入以下配置: ```python CELERY_BEAT_SCHEDULE = { 'hello_task': { 'task': 'tasks.hello', 'schedule': 10.0, }, } ``` 其,'hello_task'是任务的名称,'task'指定任务的函数名,'schedule'则指定任务执行间隔时间。 5. 启动Celery。在Django项目的根目录下执行以下命令启动Celery: ```bash celery -A your_project_name worker -l info -B ``` 其,-A参数指定Celery要加载的Django项目的名称,-B参数表示启用定时任务。 6. 测试定时任务是否生效。等待10秒钟后,可以在控制台看到输出了'Hello, World!',表示定时任务已经成功执行。 以上就是使用DjangoCelery框架来实现定时任务执行的步骤。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值