type
status
date
slug
summary
tags
category
icon
password
Last edited time
Jan 14, 2025 01:21 PM
问题描述
Celery Beat是Celery的定时调度实现,可以配置cron表达式,向broker发送任务,再由Celery Worker进行消费。Superset使用Celery Beat和Celery Worker来进行定时邮件报告的发送。
但是在发布线上环境的过程中,发现每一个配置的任务会被重复发送4次,如果我下掉一台机器,那么就只会发送3次。所以原因在于Celery Beat只支持单节点部署。由于线上环境部署了4台机器,Celery Beat被部署在4个节点上,任务也会被调度发送4次。
可以在本地环境进行测试:
分别在两个终端运行下面的命令:
--schedule是为了确保两个实例的调度文件的输出位置不相同,如果相同的话,文件会被其中一个进程锁定,。
这样配置之后, 本地就会同时发送两封邮件。
综上所述,Celery Beat存在两个不够好的地方:
- 单节点部署,难以高可用保障
- 调度的文件放在文件系统,如果实例重新部署,可能会遇到问题
解决方案
启动命令变为
同时在celery 原有的配置文件里设置
- redbeat_redis_url :celery beat调度计划的存储地址
- redbeat_key_prefix : redbeat 存储到redis 的key的前缀
启动时加上celery --app=superset.tasks.celery_app:app beat -S redbeat.RedBeatScheduler --loglevel=DEBUG查看日志
一台机器每分钟触发一次
另一台机器则
如果一台机器挂了呢,这里我停止了一个beat
新的机器过了5分钟开始接管,生成新的分布式锁
至于等待时长是5分钟的原因,是因为用了celery beat 原生的beat_max_loop_interval配置
这个配置项的意思是调度器每次检查任务调度表(schedule)的时间间隔。beat_max_loop_interval 决定了 Celery Beat 每隔多长时间检查一次这些任务是否需要被触发。但这个是最多等待时间,好比我有一个任务每分钟执行一次,Celery Beat会自动调整检查间隔。
具体规则为:
==等扫描到周期任务时,这个周期任务的间隔时间又小于celery默认扫描时间时,将以最小值时间进行休息不扫描。==
==所以当周期任务被动态添加时,并不会马上触发,而是会等待beat_max_loop_interval或者其它任务的间隔时间。==
这里为了保证时效性,Superset的最大检查间隔被设置为1min。
- 作者:很久不是自己
- 链接:https://weibo.com/article/celeryBeatDistributed
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章