apply_async 里只有 args / kwargs 才会走你配置的序列化器;直接写 ticket=instance 会被当成消息元数据,强制 JSON 序列化,从而导致报错
已于 2025年09月03日 16:57 修改
访问次数:0
好的,总结一下这个问题 ✅
问题现象
你调用:
start_pipeline.apply_async(ticket=instance)
报错:
object of type Ticket is not JSON serializable
即使已经在 Celery 配置中启用了 pickle 序列化。
根本原因
- apply_async 的参数分两类: 任务参数:需要传给任务函数的参数,要放在 args 或 kwargs 里。 消息元数据:调度、路由相关的参数(如 queue、countdown、expires 等)。
- 你把 ticket=instance 直接传给 apply_async,Celery 认为这是 消息元数据,因此强制走 JSON 序列化,而不是 pickle。
正确写法
把模型实例放到 kwargs 里:
# 正确 ✅
start_pipeline.apply_async(kwargs={'ticket': instance})
这样 Celery 会把 ticket 作为任务参数,按你配置的 pickle 序列化。
⚠️ 注意事项
- 即便能传 Django 模型实例,不推荐直接传 ORM 对象: pickle 不安全(反序列化时可能执行恶意代码)。 ORM 对象反序列化后数据库连接状态可能丢失。
- 最佳实践:传主键 ID,在任务里重新查数据库: start_pipeline.apply_async(kwargs={'ticket_id': instance.id})
✅ 一句话总结:apply_async 里只有 args / kwargs 才会走你配置的序列化器;直接写 ticket=instance 会被当成消息元数据,强制 JSON 序列化,从而导致报错。
要不要我帮你整理一张 Celery apply_async 参数分类表(任务参数 vs 调度参数),这样一看就不会混淆?
评论(0)