Celery进阶二

任务调度delay&apply_async

delay与apply_async都是用来做任务调度,但如果查看delay的源码会发现最终还是调用了apply_async,简单来说delay就是apply_async的快捷方式,而apply_async则有很多参数来控制任务调度。
apply_async支持常用参数:

  • eta:指定任务执行时间,类型为datetime时间类型;
  • countdown:倒计时,单位秒,浮点类型;
  • expires:任务过期时间,如果任务在超过过期时间还未执行则回收任务,浮点类型获取datetime类型;
  • retry:任务执行失败时候是否尝试,布尔类型。;
  • serializer:序列化方案,支持pickle、json、yaml、msgpack;
  • priority:任务优先级,有0~9优先级可设置,int类型;
  • retry_policy:任务重试机制,其中包含几个重试参数,类型是dict如下:
    • max_retries:最大重试次数

    • interval_start:重试等待时间

    • interval_step:每次重试叠加时长,假设第一重试等待1s,第二次等待1+n秒

    • interval_max:最大等待时间

Celery设置参数说明

  • CELERY_DEFAULT_QUEUE 默认队列
  • CELERY_RESULT_BACKEND 存储地址
  • CELERY_TASK_SERIALIZER 任务序列化方式
  • CELERY_RESULT_SERIALIZER 任务结果序列化方式
  • CELERY_TASK_RESULT_EXPIRES 任务过期时间
  • CELERYD_CONCURRENCY 任务并发数
  • CELERYBEAT_SCHEDULE 任务调度
  • CELERY_QUEUE 自定义任务队列

CELERY_QUEUE = (       
    Queue('default',exchange=Exchange('default'), routing_key="default.#"),     # 路由键 以 "default." 开头的消息都进入 default 队列.
    Queue('task1_app',exchange=Exchange('task1'), routing_key="task1.#")     # 路由键 以 "web." 开头的消息都进入 task1队列.
)
  • CELERY_ROUTES 自定义任务路由
CELERY_ROUTES = {

    'celery_app.app_task1.auto_crawl':{'queue':'task1','routing_key':'task1'},
    'celery_app.app_task1.auto_download':{'queue':'task1','routing_key':'task1'},
    'celery_app.app_task1.timelycrawl': {'queue': 'task2', 'routing_key': 'task2'},
    'celery_app.app_task1.timelydownload': {'queue': 'task2', 'routing_key': 'task2'}
}
  • CELERY_ACCEPT_CONTENT 指定过任务接受内容的格式

CELERYBEAT_SCHEDULE = {
    'add': {
        'task': 'proj.tasks.add', #任务的路劲
        'schedule': timedelta(seconds=10), #定时启动时间,也可以用crontab
        'args': (16, 16) #任务参数  
    }

Celery的存储问题

在使用定时任务的时候我发现了一个问题,就是当你有两个定时任务(task1,task2)时,两个的定时时间相同比如都是一分钟,
然后task1的执行时间较长要2分钟,而task2的执行时间只要两秒,理想状态下是task1在执行但因为时间较长,会挂起,然后在挂起的时间里定时的去执行task2。但实际情况下,当进行task1的时候,在task1未执行完的时候,task2并不执行,然后当task1执行完时,task2会立马执行好几次。
下图就是,celery的流程:


image.png

从该图可以看出,造成该原因的是因为只有一个Woker,在从任务队列里面拿出一个任务时,在没执行完当前任务的时候是不会在往任务队列里面拿去任务,但task2在每两秒内会往该任务队列里面放入任务,所以根据队列先进先出的原则,在task1执行完时,会立马执行好几次的task2

解决方案:

image.png

解决的方法就是,增加并发数,也就是在设置里面添加CELERYD_CONCURRENCY参数,每个woker在闲空的时候就会自动去任务队列里面拿任务就不会造成任务阻塞。

所以定时任务最好不要放多个互相之间有依赖关系的任务

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.在一些复杂的处理中,使用队列 在settings.py中添加 2.启动特定队列处理任务 celery -A p...
    第八共同体阅读 372评论 0赞 0
  • Celery 在程序的运行过程中,我们经常会碰到一些耗时耗资源的操作,为了避免它们阻塞主程序的运行,我们经常会采用...
    HAO延WEI阅读 3,607评论 1赞 5
  • 一、前言 上一篇文章iOS多线程浅汇-原理篇中整理了一些有关多线程的基本概念。本篇博文介绍的是iOS中常用的几个多...
    nuclear阅读 2,173评论 6赞 18
  • Celery 在程序运行过程中,经常会遇到一些耗时耗资源的任务,为了避免这些任务阻塞主进程的运行,我们会采用多线程...
    玩阿轲睡妲己阅读 9,204评论 1赞 9
  • 一、前言 本篇博文介绍的是iOS中常用的几个多线程技术: NSThread GCD NSOperation 由于a...
    和珏猫阅读 680评论 0赞 1

友情链接更多精彩内容