• celery


    1.什么是Celery?

    Celery 是芹菜
    Celery 是基于Python实现的模块, 用于执行异步定时周期任务的
    其结构的组成是由
        1.用户任务 app
        2.管道 broker 用于存储任务 官方推荐 redis rabbitMQ  / backend 用于存储任务执行结果的
        3.员工 worker

    2.Celery的简单实例

     1 from celery import Celery
     2 import time
     3 
     4 #创建一个Celery实例,这就是我们用户的应用app
     5 my_task = Celery("tasks", broker="redis://127.0.0.1:6379", backend="redis://127.0.0.1:6379")
     6 
     7 # 为应用创建任务,func1
     8 @my_task.task
     9 def func1(x, y):
    10     time.sleep(15)
    11     return x + y
    s1.py
    1 from s1 import func1
    2 
    3 # 将任务交给Celery的Worker执行
    4 res = func1.delay(2,4)
    5 
    6 #返回任务ID
    7 print(res.id)
    s2.py
     1 from celery.result import AsyncResult
     2 from s1 import my_task
     3 
     4 # 异步获取任务返回值
     5 async_task = AsyncResult(id="31ec65e8-3995-4ee1-b3a8-1528400afd5a",app=my_task)
     6 
     7 # 判断异步任务是否执行成功
     8 if async_task.successful():
     9     #获取异步任务的返回值
    10     result = async_task.get()
    11     print(result)
    12 else:
    13     print("任务还未执行完成")
    s3.py

    三个文件创建完成了,细心的同学现在已经开始分析哪个文件是app,哪个文件是borker,哪个是worker了
    那我们得一步一步分析了,最终我们要执行的任务是在 s1.py 中,也就是worker需要执行的任务,所以worker就是 s1.py了
    现在我们就来启动worker,如何启动呢
    根据操作系统的不同,启动方式也存在差异:
    Linux - celery worker -A s1 -l INFO
    Windows:这里需要注意的是celery 4.0 已经不再对Windows操作系统提供支持了,也就是在windows环境下出现问题除非自己解决,否贼官方是不会给你解决的
    Windows - celery worker -A s1 -l INFO -P eventlet
    ps: eventlet 是一个python的三方库 需要使用 pip安装 pip install eventlet

    启动完成,其实在s1.py当中,worker已经知道了自己的broker 和 backend 在哪里了
    接下来就让异步任务开始执行吧,对了 s2.py 中就是使用 delay 的方式来开始执行的异步任务
    执行 s2.py 得到了一个字符串 55a84ea3-afa4-4ab9-8650-40e156c07441 这个字符串儿就是异步任务的ID
    在Celery worker 的控制台中可以看到这个样子

    等待15秒钟之后就可以的到这样一个字符串

    然后通过s3.py修改异步任务的ID来获取任务返回的结果

    这样就简单完成了一个Celery异步任务了

    3.Celery 结合 Flask 模拟"抢购"系统

    https://pan.baidu.com/s/15T08QUBYWqi8QjE0sPUBlg

    下载源码查看示例

    4.Celery项目目录

    在实际项目中我们应用Celery是有规则的

    要满足这样的条件才可以哦,目录Celery_task这个名字可以随意起,但是一定要注意在这个目录下一定要有一个celery.py这个文件

    1 from celery import Celery
    2 
    3 celery_task = Celery("task",
    4                      broker="redis://127.0.0.1:6379",
    5                      backend="redis://127.0.0.1:6379",
    6                      include=["Celery_task.task_one","Celery_task.task_two"])
    7 # include 这个参数适用于寻找目录中所有的task
    celery.py
    1 from .celery import celery_task
    2 import time
    3 
    4 @celery_task.task
    5 def one(x,y):
    6     time.sleep(5)
    7     return f"task_one {x+y}"
    task_one
    1 from .celery import celery_task
    2 import time
    3 
    4 @celery_task.task
    5 def two(x,y):
    6     time.sleep(5)
    7     return f"task_two {x+y}"
    task_two

    这样Celery项目目录结构就已经做好了然后再 my_celery中调用

    1 from Celery_task.task_one import one
    2 from Celery_task.task_two import two
    3 
    4 one.delay(10,10)
    5 two.delay(20,20)
    my_celery.py

    PS:启动Worker的时候无需再使用文件启动,直接启动你的Celery_task目录就行了
    celery worker -A Celery_task -l INFO -P eventlet

    celery worker --help   查看具体参数

    celery worker -A Celery_task -l INFO -P eventlet  -c 6  #开启6个worker,最大开启25
    这样celery就可以自动的去检索当前目录下所有的task了,通过Include这个参数逐一去寻找
     

    5.Celery定时任务
    我们还使用Celery_task这个示例来修改一下
    my_celery中进行一下小修改

     1 from Celery_task.task_one import one
     2 from Celery_task.task_two import two
     3 
     4 # one.delay(10,10)
     5 # two.delay(20,20)
     6 
     7 # 定时任务我们不在使用delay这个方法了,delay是立即交给task 去执行
     8 # 现在我们使用apply_async定时执行
     9 
    10 #首先我们要先给task一个执行任务的时间
    11 import datetime,time
    12 # 获取当前时间 此时间为东八区时间
    13 ctime = time.time()
    14 # 将当前的东八区时间改为 UTC时间 注意这里一定是UTC时间,没有其他说法
    15 utc_time = datetime.datetime.utcfromtimestamp(ctime)
    16 # 为当前时间增加 10 秒
    17 add_time = datetime.timedelta(seconds=10)
    18 action_time = utc_time + add_time
    19 
    20 # action_time 就是当前时间未来10秒之后的时间
    21 #现在我们使用apply_async定时执行
    22 res = one.apply_async(args=(10,10),eta=action_time)
    23 print(res.id)
    24 #这样原本延迟5秒执行的One函数现在就要在10秒钟以后执行了
    my_celery

    定时任务只能被执行一次,那如果我想每隔10秒都去执行一次这个任务怎么办呢? 周期任务来了

    6.Celery周期任务

    首先要对Celery_task中的celery.py进行一点修改:

     1 from celery import Celery
     2 from celery.schedules import crontab
     3 
     4 celery_task = Celery("task",
     5                      broker="redis://127.0.0.1:6379",
     6                      backend="redis://127.0.0.1:6379",
     7                      include=["Celery_task.task_one","Celery_task.task_two"])
     8 
     9 #我要要对beat任务生产做一个配置,这个配置的意思就是每10秒执行一次Celery_task.task_one任务参数是(10,10)
    10 celery_task.conf.beat_schedule={
    11     "each10s_task":{
    12         "task":"Celery_task.task_one.one",
    13         "schedule":10, # 每10秒钟执行一次
    14         "args":(10,10)
    15     },
    16     "each1m_task": {
    17         "task": "Celery_task.task_one.one",
    18         "schedule": crontab(minute=1), # 每一分钟执行一次
    19         "args": (10, 10)
    20     },
    21     "each24hours_task": {
    22         "task": "Celery_task.task_one.one",
    23         "schedule": crontab(hour=24), # 每24小时执行一次
    24         "args": (10, 10)
    25     }
    26 
    27 }
    28 
    29 #以上配置完成之后,还有一点非常重要
    30 # 不能直接创建Worker了,因为我们要执行周期任务,所以首先要先有一个任务的生产方
    31 # celery beat -A Celery_task
    32 # celery worker -A Celery_task -l INFO -P eventlet
    celery.py

    创建Worker的方式并没有发行变化,但是这里要注意的是,每间隔一定时间后需要生产出来任务给Worker去执行,这里需要一个生产者beat

    celery beat -A Celery_task  #创建生产者 beat 你的 schedule 写在哪里,就要从哪里启动

     celery worker -A Celery_task -l INFO -P eventlet

     创建worker之后,每10秒就会由beat创建一个任务给Worker去执行

    到此为止 Celery的应用就已经完事儿了,Bye



     
     
     
  • 相关阅读:
    vue 中的键盘事件
    红米k40刷类原生系统
    (历史) 1960s,大家争先在共享内存上实现原子性 (互斥) 但几乎所有的实现都是错的,直到 Dekker's Algorithm,还只能保证两个线程的互斥
    Go Memory Model 内存模型 同步 goroutine
    理解并发程序执行 (Peterson算法、模型检验与软件自动化工具
    源码 连接池 设计
    Thread Exception Captured Application Crash Report
    Check if the context is expired.
    A Quick Guide to Go's Assembler
    敏感问题调查 干扰变量 抛硬币
  • 原文地址:https://www.cnblogs.com/feifeifeisir/p/10397282.html
Copyright © 2020-2023  润新知