apply_async 里只有 args / kwargs 才会走你配置的序列化器;直接写 ticket=instance 会被当成消息元数据,强制 JSON 序列化,从而导致报错

好的,总结一下这个问题 ✅



问题现象

你调用:

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)