前面咱们了解了celery的基本使用后,如今对其经常使用的对象和方法进行分析。html
核心的对象就是Celery了,初始化方法:python
class Celery(object): def __init__(self, main=None, loader=None, backend=None, amqp=None, events=None, log=None, control=None, set_as_current=True, accept_magic_kwargs=False, tasks=None, broker=None, include=None, changes=None, config_source=None, fixups=None, task_cls=None, autofinalize=True, **kwargs): # 经常使用的须要配置的参数 main:若是做为__main__运行,则为主模块的名称。用做自动生成的任务名称的前缀 loader:当前加载器实例。 backend:任务结果url; amqp:AMQP对象或类名,通常无论; log:日志对象或类名; set_as_current:将本实例设为全局当前应用 tasks:任务注册表。 broker:使用的默认代理的URL,任务队列; include:每一个worker应该导入的模块列表,以实例建立的模块的目录做为起始路径;
这些参数都是celery实例化的配置,咱们也能够不写,而后使用config_from_object方法加载配置;web
任何被task修饰的方法都会被建立一个Task对象,变成一个可序列化并发送到远程服务器的任务;它有多种修饰方式:redis
@celery.task def function_name(): pass
@celery.task(bind=True, name='name') def function_name(): pass # task方法参数 name:能够显式指定任务的名字;默认是模块的命名空间中本函数的名字。 serializer:指定本任务的序列化的方法; bind:一个bool值,设置是否绑定一个task的实例,若是绑定,task实例会做为参数传递到任务方法中,能够访问task实例的全部的属性,即前面反序列化中那些属性 base:定义任务的基类,能够以此来定义回调函数,默认是Task类,咱们也能够定义本身的Task类 default_retry_delay:设置该任务重试的延迟时间,当任务执行失败后,会自动重试,单位是秒,默认3分钟; autoretry_for:设置在特定异常时重试任务,默认False即不重试; retry_backoff:默认False,设置重试时的延迟时间间隔策略; retry_backoff_max:设置最大延迟重试时间,默认10分钟,若是失败则再也不重试; retry_jitter:默认True,即引入抖动,避免重试任务集中执行;
# 当bind=True时,add函数第一个参数是self,指的是task实例 @task(bind=True) # 第一个参数是self,使用self.request访问相关的属性 def add(self, x, y): try: logger.info(self.request.id) except: self.retry() # 当任务失败则进行重试
import celery class MyTask(celery.Task): # 任务失败时执行 def on_failure(self, exc, task_id, args, kwargs, einfo): print('{0!r} failed: {1!r}'.format(task_id, exc)) # 任务成功时执行 def on_success(self, retval, task_id, args, kwargs): pass # 任务重试时执行 def on_retry(self, exc, task_id, args, kwargs, einfo): pass @task(base=MyTask) def add(x, y): raise KeyError() #方法相关的参数 exc:失败时的错误的类型; task_id:任务的id; args:任务函数的参数; kwargs:键值对参数; einfo:失败或重试时的异常详细信息; retval:任务成功执行的返回值;
Task.name:任务名称; Task.request:当前任务的信息; Task.max_retries:设置重试的最大次数 Task.throws:预期错误类的可选元组,不该被视为实际错误,而是结果失败; Task.rate_limit:设置此任务类型的速率限制 Task.time_limit:此任务的硬限时(以秒为单位)。 Task.ignore_result:不存储任务状态。默认False; Task.store_errors_even_if_ignored:若是True,即便任务配置为忽略结果,也会存储错误。 Task.serializer:标识要使用的默认序列化方法的字符串。 Task.compression:标识要使用的默认压缩方案的字符串。默认为task_compression设置。 Task.backend:指定该任务的结果存储后端用于此任务。 Task.acks_late:若是设置True为此任务的消息将在任务执行后确认 ,而不是在执行任务以前(默认行为),即默认任务执行以前就会发送确认; Task.track_started:若是True任务在工做人员执行任务时将其状态报告为“已启动”。默认是False;
调用异步任务有三个方法,以下:json
task.delay():这是apply_async方法的别名,但接受的参数较为简单; task.apply_async(args=[arg1, arg2], kwargs={key:value, key:value}):能够接受复杂的参数 send_task():能够发送未被注册的异步任务,即没有被celery.task装饰的任务;
# tasks.py from celery import Celery app = Celery() def add(x,y): return x+y app.send_task('tasks.add',args=[3,4]) # 参数基本和apply_async函数同样 # 可是send_task在发送的时候是不会检查tasks.add函数是否存在的,即便为空也会发送成功,因此celery执行是可能找不到该函数报错;
delay方法是apply_async方法的简化版,不支持执行选项,只能传递任务的参数。flask
@app.task def add(x, y, z=0): return x + y add.delay(30,40,z=5) # 包括位置参数和关键字参数
apply_async支持执行选项,它会覆盖全局的默认参数和定义该任务时指定的执行选项,本质上仍是调用了send_task方法;后端
add.apply_async(args=[30,40], kwargs={'z':5}) # 其余参数 task_id:为任务分配惟一id,默认是uuid; countdown : 设置该任务等待一段时间再执行,单位为s; eta : 定义任务的开始时间;eta=time.time()+10; expires : 设置任务时间,任务在过时时间后尚未执行则被丢弃; retry : 若是任务失败后, 是否重试;使用true或false,默认为true shadow:从新指定任务的名字str,覆盖其在日志中使用的任务名称; retry_policy : {},重试策略.以下: max_retries : 最大重试次数, 默认为 3 次. interval_start : 重试等待的时间间隔秒数, 默认为 0 , 表示直接重试不等待. interval_step : 每次重试让重试间隔增长的秒数, 能够是数字或浮点数, 默认为 0.2 interval_max : 重试间隔最大的秒数, 即 经过 interval_step 增大到多少秒以后, 就不在增长了, 能够是数字或者浮点数, 默认为 0.2 . routing_key:自定义路由键; queue:指定发送到哪一个队列; exchange:指定发送到哪一个交换机; priority:任务队列的优先级,0到255之间,对于rabbitmq来讲0是最高优先级; serializer:任务序列化方法;一般不设置; compression:压缩方案,一般有zlib, bzip2 headers:为任务添加额外的消息; link:任务成功执行后的回调方法;是一个signature对象;能够用做关联任务; link_error: 任务失败后的回调方法,是一个signature对象; # 以下 add.apply_async((2, 2), retry=True, retry_policy={ 'max_retries': 3, 'interval_start': 0, 'interval_step': 0.2, 'interval_max': 0.2, })
task.apply_async((2,2), compression='zlib', serialize='json', queue='priority.high', routing_key='web.add', priority=0, exchange='web_exchange')
因为celery发送的都是去其余进程执行的任务,若是须要在客户端监控任务的状态,有以下方法:服务器
r = task.apply_async() r.ready() # 查看任务状态,返回布尔值, 任务执行完成, 返回 True, 不然返回 False. r.wait() # 会阻塞等待任务完成, 返回任务执行结果,不多使用; r.get(timeout=1) # 获取任务执行结果,能够设置等待时间,若是超时但任务未完成返回None; r.result # 任务执行结果,未完成返回None; r.state # PENDING, START, SUCCESS,任务当前的状态 r.status # PENDING, START, SUCCESS,任务当前的状态 r.successful # 任务成功返回true r.traceback # 若是任务抛出了一个异常,能够获取原始的回溯信息
可是通常业务中不多用到,由于获取任务执行的结果须要阻塞,celery使用场景通常是不关心结果的。并发
# seting.py # 设置配置 BROKER_URL = 'amqp://username:password@localhost:5672/yourvhost' CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' CELERY_TASK_SERIALIZER = 'msgpack' CELERY_RESULT_SERIALIZER = 'msgpack' CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24 CELERY_ACCEPT_CONTENT = ["msgpack"] CELERY_DEFAULT_QUEUE = "default" CELERY_QUEUES = { "default": { # 这是上面指定的默认队列 "exchange": "default", "exchange_type": "direct", "routing_key": "default" } } # app.py --- 初始化celery对象 from celery import Celery import seting from task import test_one, test_two celery = Celery(__name__, include=["task"]) # 设置须要导入的模块 # 引入配置文件 celery.config_from_object(seting) if __name__ == '__main__': test_one.apply_async((2,2), routing_key='default', priority=0, exchange='default') # task.py --- 定义须要执行的任务 from app import celery @celery.task def test_one(x, y): return x + y @celery.task(name="one_name") def test_two(x, y): return x * y
分析了celery任务一些方法参数和相关源码,接下来咱们去研究celery更复杂的用法。app
http://docs.celeryproject.org/en/latest/userguide/tasks.html#task-options
http://docs.jinkan.org/docs/celery/getting-started/first-steps-with-celery.html
http://www.pythondoc.com/flask-celery/first.html
https://blog.csdn.net/kk123a/article/details/74549117
https://blog.csdn.net/preyta/article/details/54288870