- Application
- application
celery 在使用之前, 必须首先实例化. e.g. App = Celery()
App 是线程安全的, 即: 不同配置, 组件和任务的多个 App 可以共存在同一个进程空间.
任务注册表(task-registry)
在 Celery 中发送一个 task 消息, 这个消息并不包含任何源代码 (函数体). 而是只有你所期望执行的 task 的名字. 每个 worker 有一个任务注册表(task-registry), 它是 task 名称与 task 源代码(函数) 的映射. 每当你定义一个 task, 这个 task 就会被注册到本地的注册表中
懒加载
Celery 创建 App 实例是延迟的, 只有在调用它的时候才会创建. 也就是说, Celery()命令并没有立即创建 App 实例.
Celery 实例化的过程中, 做了如下操作:
创建了一个逻辑时钟, 用于 events
创建了一个任务注册表 task-registry
设置它自己为当前的 Celery 实例(如果 set_as_current 参数被置为 disabled, 那么就不会进行该操作)
调用 App.on_init() (默认情况下, 啥都没做)
@App.task 装饰器也是延迟创建 task 的. task 被定义的时候(在一个函数头上加装饰器的时候),task 并没有立即创建. 在 task 被使用的时候, 或者是 App finalized 的时候, task 才会创建
finalized 做了如下操作:
task 是在多 App 之间共享的, 拷贝 task.(shard 参数可以取消共享, 使 task 独属于其绑定的 App)
创建所有的 task
确保所有的 task 都绑定到当前的 App(只有绑定 App,task 才能读取默认的配置)
Main name
task 默认的名称组成是 model.fun e.g. tasks.add .
当 model 名获取不到的时候就会以 __main__ 作为 model 名. 因此会出现 某 task 以 __main__.add 为名注册到 任务注册表之后, 当某个 task 被引入到其他模块时, 会以源模块. task 作为任务名, 这个时候, 就会出现不一致的情况, 所以, 在 Celery 实例化的时候一定要指定 App 的名字. e.g. App=Celery('tasks')
配置 Celery
Celery 的配置有如下几种:
直接配置 App 属性
使用配置文件
直接配置 App 属性
单个配置
App.conf.enable_utc = True
多个配置
App.conf.update(enable_utc=True, timezone='Asia/Shanghai')
使用配置文件
从配置文件加载配置, 使用 App.config_from_object() 和 App.config_from_envvar()方法.
- config_from_object
- App = Celery()
- App.config_from_object('celeryconfig.py')
- # 项目中要有 celeryconfig.py 文件
- from xxxx import configmodel
- App = Celery()
- App.config_from_object(configmodel)
- class Config:
- enable_utc = True
- App = Celery()
- App.config_from_object(Config)
- config_from_envva
从环境变量加载指定模块
- App.config_from_envvar('CELERY_CONFIG_MODEL')
- Task
所有使用 @task() 装饰器定义的 task, 都继承自基类 Task . 你也可以指定自己的基类 Task.
在装饰器中指定其他类
- @App.task(base=OtherTask)
- def function():
- ...
在配置中指定其他类
- App = Celery()
- App.Task = OtherTask
自定义 Task
所有的自定义 Task 都必须
继承自 Task 类
- class MyTask(Task):
- ...
最佳实践是 App 作为参数传给需要它的地方
- class SomeClass:
- def __init__(self, App):
- self.App = App
- ...
来源: http://www.bubuko.com/infodetail-2825099.html