Celery 限速报 KeyError,或只跑第一条:核对 rate_limit
Celery 5.6.3 的未知限速单位可抛 KeyError,负速率则进入令牌桶。使用有效单位与认可的非负预算,区分每 worker 限速,并核对已有等待任务,不能用 0 暂停。
Celery worker 启动时在限速初始化中报 KeyError: 'x',或者某类任务只执行第一条、后续一直留在等待状态,应检查该任务实际注册的 rate_limit。'10/x' 与 '-5/m' 都不是可用的业务限速配置,但旧实现的失败表现并不直观。
在正式 Celery 5.6.3 中,速率字符串按 / 拆分,单位直接查映射表。未知单位会抛 KeyError;远程限速处理只捕获 ValueError,所以未必能返回预期的“非法限速字符串”响应。不能把没有收到这条错误回复理解为设置有效。
负数不会表示暂停任务
'-5/m' 可以被转换为负的每秒速率,并用于建立容量为 1 的令牌桶。Kombu 5.6.2 的补充令牌和等待时间计算没有把它当作合法暂停状态:初始令牌可能让第一条执行,后续调度仍无法得到正常的补充预算。
这是一条解释等待的具体路径,不代表所有任务停滞都由负数引起。先关联任务名、worker、配置来源、接收和开始执行记录;broker 断连、ETA、依赖任务与并发槽位耗尽仍需按实际日志区分。
可用格式采用每秒、每分钟或每小时的非负速率,单位为 s、m、h。例如,下面只示范已有 Celery 应用中一个任务的定义:
@app.task(name="jobs.refresh_item", rate_limit="5/m")
def refresh_item(item_id):
return update_existing_item(item_id)
app 和 update_existing_item 是项目已有对象,5/m 仅为格式示例,实际数值由接口容量决定。Celery 的任务限速以 worker 为单位,多台 worker 不会自动共享一份全局每分钟预算;它也不会停止已经开始执行的任务。
0 或关闭限速的配置表示不限速,不是暂停。需要暂停消费或限制某个业务入口时,应使用经过评估的队列与调度控制,不能设置负速率,也不能靠把单位改成不存在的值阻断启动。
修配置与核对滞留任务一起做
从任务属性、注解和运行时限速修改等入口找到最终值,恢复经过确认的格式,并让生产者与目标 worker 的代码和配置保持一致。对来自外部配置的速率,在进入 Celery 前拒绝负数、未知单位及非有限数值,不能仅以旧 rate() 没有抛 ValueError 作为合法性判断。
已有等待任务需要保留任务标识和执行记录,通过应用既有切换流程处理。重新设置限速会重建桶,不能承诺它自动找回所有旧桶中的等待项;不要清队列或把全部任务重新提交作为验证。正常关闭、重启及重新投递仍受确认时机和 broker 规则影响,涉及业务副作用时按幂等记录核对。
在隔离队列观察多条同类任务的开始时间和最终业务结果,覆盖首次令牌与后续补充阶段,并检查多个 worker 的总速率。回退时恢复原先认可的配置,不恢复已确认无效的字符串;日志显示任务成功也不能代替结果完整性核验。


