Celery框架

摘要:

在了解celery的异步任务队列之前我们来先了解下Node 似乎我与人聊过了node.js这个框架,他是一个简单运行将js运行在服务器上的

非阻塞的异步框架,一个线程就可以跑起整个项目,但是我想强调的是他的

异步非阻塞和事件驱动!他是怎么把通过一个线程处理这么多请求的,处理一个请求不会阻塞吗?请听我一一道来!

nodejs最大的优势在于一个请求过来,他接入请求,并处理他,当事件遇到一些io操作的时候,就把他的事件丢在一个队列里面,我们称之为

队列(其实并不是栈区,栈是先进后出的概念,我们说他是队列),然后依次排队处理栈,等处理完之后又继续处理请求,栈区发出一个完成信号的时候,继续处理栈区内容,就做到异步非阻塞,而他的事件驱动就是这个队列区完成io操作的信号驱使。

什么是celery

目前不支持win平台,但是我们处理后依旧可以使用

聊完这个nodejs这个东西之后,我们引出了一个celery这个框架,他和nodejs相似但是他是一个简单的可靠的分布式系统

他专注于实时处理异步任务队列 同时也支持任务调度

celery三部分

消息中间件   不是celery的自己创立而是第三方  redis(也支持在中间件里)

执行单元  工人 处理执行单元任务的函数

消息结果存储 可以理解数据库 同样的用第三方

我们在哪里用?

说实在的我们标题就能理解出 他是异步框架 所以适合大量io密集型的场景(或耗时任务)

已经他自己支持定时调度 比如每天凌晨把日志同步起来 或者更新下缓存

好牛逼 在python咋用?

pip install celery  下载这个框架 不建议使用Django的

定义执行任务的函数

#把我们的函数装饰为异步执行任务
import celery
import time
# broker='redis://127.0.0.1:6379/2' #版本不加密码
backend='redis://:123456@127.0.0.1:6379/1' #任务提交后放在这个库里
broker='redis://:123456@127.0.0.1:6379/2' #任务执行完后结果的db
cel=celery.Celery('test',backend=backend,broker=broker) 
#装饰函数
@cel.task
def add(x,y):
    return x+y

 

 创造一个可以开启任务功能的模块

from celery_app_task import add
result = add.delay(4,5) #4,5为参数  #启动任务
print(result.id)  #拿到这个用于查看任务的CDK

启动我们的功能

celery worker -A celery_app_task -l info  其他平台
celery worker -A celery_app_task -l info -P eventlet #window

函数启动
from celery_app_task import cel
if __name__ == '__main__':
    cel.worker_main()

查看结果

async = AsyncResult(id="e919d97d-2938-4d0f-9265-fd8237dc2aa3", app=cel)#r任务序列号

if async.successful():
    result = async.get()
    print(result)
    # result.forget() # 将结果删除
elif async.failed():
    print('执行失败')
elif async.status == 'PENDING':
    print('任务等待中被执行')
elif async.status == 'RETRY':
    print('任务异常后正在重试')
elif async.status == 'STARTED':
    print('任务已经开始被执行')

多任务结果

可能用户任务 和订单任务是分开的 所以我们需要多任务 ,之前一个肯定是不行了

pro_cel
    ├── celery_task# celery相关文件夹
    │   ├── celery.py   # celery连接和配置相关文件,必须叫这个名字
    │   └── tasks1.py    #  所有任务函数
    │    └── tasks2.py    #  所有任务函数
    ├── check_result.py # 检查结果
    └── send_task.py    # 触发任务

任务文件

import time
from celery_task.celery import cel

#test1.py
@cel.task
def test_celery(res):
    time.sleep(5)
    return "test_celery任务结果:%s"%res

#test2.py
import time
from celery_task.celery import cel
@cel.task
def test_celery2(res):
    time.sleep(5)
    return "test_celery2任务结果:%s"%res

 celery.py 任务分发作用

from celery import Celery

cel = Celery('celery_demo',
             broker='redis://127.0.0.1:6379/1',
             backend='redis://127.0.0.1:6379/2',
             # 包含以下两个任务文件,去相应的py文件中找任务,对多个任务做分类
             include=['celery_task.tasks1',
                      'celery_task.tasks2'
                      ])

# 时区
cel.conf.timezone = 'Asia/Shanghai'
# 是否使用UTC
cel.conf.enable_utc = False

拿到任务CDK

from celery_task.tasks1 import test_celery
from celery_task.tasks2 import test_celery2

# 立即告知celery去执行test_celery任务,并传入一个参数
result = test_celery.delay('第一个的执行')
print(result.id)
result = test_celery2.delay('第二个的执行')
print(result.id)

查看结果

from celery.result import AsyncResult
from celery_task.celery import cel

async = AsyncResult(id="08eb2778-24e1-44e4-a54b-56990b3519ef", app=cel)  #任务序列号

if async.successful():
    result = async.get()
    print(result)
    # result.forget() # 将结果删除,执行完成,结果不会自动删除
    # async.revoke(terminate=True)  # 无论现在是什么时候,都要终止
    # async.revoke(terminate=False) # 如果任务还没有开始执行呢,那么就可以终止。
elif async.failed():
    print('执行失败')
elif async.status == 'PENDING':
    print('任务等待中被执行')
elif async.status == 'RETRY':
    print('任务异常后正在重试')
elif async.status == 'STARTED':
    print('任务已经开始被执行')

开启work

celery worker -A celery_task -l info  -P  eventlet

开启任务

send_task.py
检查任务执行结果
(执行check_result.py)

定时任务

本质:使用apply_async并设定时间    参数eta传递要执行的事件

from celery_app_task import add
from datetime import datetime

# 方式一
# v1 = datetime(2019, 2, 13, 18, 19, 56)
# print(v1)
# v2 = datetime.utcfromtimestamp(v1.timestamp())
# print(v2)
# result = add.apply_async(args=[1, 3], eta=v2)
# print(result.id)

# 方式二
ctime = datetime.now()
# 默认用utc时间
utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
from datetime import timedelta
time_delay = timedelta(seconds=10)
task_time = utc_ctime + time_delay

# 使用apply_async并设定时间
result = add.apply_async(args=[4, 3], eta=task_time)
print(result.id)

像Linux的contab任务

本质cel.conf.beat_schedule = { ‘任务1’:{‘tas’:'任务',schedule:"执行频率",args:“参数”  } ,‘任务二’:{} }

 

 

from datetime import timedelta
from celery import Celery
from celery.schedules import crontab

cel = Celery('tasks', broker='redis://127.0.0.1:6379/1', backend='redis://127.0.0.1:6379/2', include=[
    'celery_task.tasks1',
    'celery_task.tasks2',
])
cel.conf.timezone = 'Asia/Shanghai'
cel.conf.enable_utc = False

cel.conf.beat_schedule = {
    # 名字随意命名
    'add-every-10-seconds': {
        # 执行tasks1下的test_celery函数
        'task': 'celery_task.tasks1.test_celery',
        # 每隔2秒执行一次
        # 'schedule': 1.0,
        # 'schedule': crontab(minute="*/1"),
        'schedule': timedelta(seconds=2),
        # 传递参数
        'args': ('test',)
    },
    # 'add-every-12-seconds': {
    #     'task': 'celery_task.tasks1.test_celery',
    #     每年4月11号,8点42分执行
    #     'schedule': crontab(minute=42, hour=8, day_of_month=11, month_of_year=4),
    #     'schedule': crontab(minute=42, hour=8, day_of_month=11, month_of_year=4),
    #     'args': (16, 16)
    # },
}

启动beat:

celery beat -A celery_task -l info

启动work:

celery worker -A celery_task -l info -P  eventlet

 

Django 引入celeary

在项目目录下创建celeryconfig.py

import djcelery
djcelery.setup_loader()
CELERY_IMPORTS=(
    'app01.tasks',
)
#有些情况可以防止死锁
CELERYD_FORCE_EXECV=True
# 设置并发worker数量
CELERYD_CONCURRENCY=4
#允许重试
CELERY_ACKS_LATE=True
# 每个worker最多执行100个任务被销毁,可以防止内存泄漏
CELERYD_MAX_TASKS_PER_CHILD=100
# 超时时间
CELERYD_TASK_TIME_LIMIT=12*30

settings.py

INSTALLED_APPS = [
    ...
    'djcelery',
    'app01'
]
from djagocele import celeryconfig
BROKER_BACKEND='redis'
BOOKER_URL='redis://127.0.0.1:6379/1'
CELERY_RESULT_BACKEND='redis://127.0.0.1:6379/2'

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值