Machinery注册任务函数必须严格为func(interface{}) error,否则静默失败;broker与result_backend需带完整协议且Redis DB隔离;定时任务须配合分布式锁防重复。

注册任务函数必须是 func(interface{}) error
这是 Machinery 最容易栽跟头的地方:它不接受任何其他签名。哪怕你只多返回一个 int,或者参数写成 func(email string, subject string) error,worker 启动时不会报错,但任务永远不执行,日志里只有 waiting for tasks。
- 必须把所有参数打包进
interface{},内部再用类型断言或结构体解包:func SendEmail(args interface{}) error { data := args.(map[string]interface{}); email := data["email"].(string); ... } - 结构体字段必须加
json:tag,否则序列化后为空 —— 比如type EmailArgs struct { To string `json:"to"` Subject string `json:"subject"` } -
time.Time不能直接塞进args,JSON 不认;转成Unix()或Format(time.RFC3339)字符串再传
Broker 和 ResultBackend 必须协议完整且 DB 隔离
配置写错几乎不报错,但 worker 就收不到任务。最常见的是协议缺省、地址混用。
-
Broker地址必须带协议:用 Redis 就写redis://123456@localhost:6379/0,不能只写localhost:6379 -
ResultBackend不能和Broker共用同一个 Redis 实例的同一 DB(比如都用/0),否则并发写冲突会导致任务丢弃;建议 broker 用/0,backend 用/1或换memcache:// - 启动前手动验证连通性:
redis-cli -u redis://localhost:6379/0 ping和redis-cli -u redis://localhost:6379/1 ping
发送任务时 Args.Type 只能是基础类型名
SendTask 不校验参数类型,发出去就“成功”,但 worker 端反序列化失败,静默跳过。问题出在 Signature.Args 的 Type 字段。
- 只允许填 Go 基础类型名:
"string"、"int"、"float64"、"bool"、"[]string"等 - 不能写自定义类型别名(如
"MyInt")、不能写"map[string]interface{}"(JSON 不支持 interface{} 键)、不能写"[]byte"(会被当成二进制乱码) - nil 切片会序列化为
null,worker 端需主动判空;嵌套过深的 struct 容易触发 JSON 递归限制,建议扁平化传参
定时任务得靠外部 cron + 分布式锁补足
Machinery 本身不提供分布式定时调度能力,RegisterPeriodicTask 是单机内存级的,集群部署下会重复触发。
立即学习“go语言免费学习笔记(深入)”;
- 要用
github.com/robfig/cron/v3这类库在每台机器上跑 cron,但必须配合 Redis 分布式锁(比如用Redlock或SETNX)确保仅一节点真正下发任务 - 锁 key 建议包含任务标识 + 下次执行时间戳,过期时间设为略大于任务执行耗时(比如 30s),避免死锁
- 任务 signature 中的
ETA必须是 Unix 时间戳(秒级或纳秒级整数),不是time.Time对象
func(interface{}) error、broker/backend 地址协议和 DB 号手动分离、定时任务没加分布式锁导致重复执行。这三处任一出错,系统都不会报错,只会“看起来在运行,其实什么都没干”。


















