Machinery需手动配置协议、类型校验、重试等,URL须带完整协议如redis://localhost:6379/0;任务函数签名必须为func(interface{}) error;参数须JSON可序列化;延迟靠ETA时间戳,重试需显式设RetryCount和RetryTimeout。

machinery 不会自动加载配置,也不会帮你补协议、校验类型、重试失败任务——所有这些都得你手动写对,否则它就静默卡住或 panic。
broker 和 result_backend 的 URL 必须带完整协议
machinery 不会给你自动补 redis:// 或 amqp://。写成 localhost:6379 或 127.0.0.1:5672 看似省事,实际会导致 worker 启动后一直卡在 “waiting for tasks”,日志里还不报错。
- ✅ 正确写法:
redis://123456@localhost:6379/0、amqp://guest:guest@localhost:5672/ - ❌ 错误写法:
localhost:6379、redis://localhost(缺端口)、amqp://localhost:5672(缺 vhost) - 如果用 Redis 做 broker 和 result_backend,别共用同一个 DB;建议 broker 用 DB 0,result_backend 用 DB 1,否则并发写可能丢结果
任务函数签名必须严格为 func(interface{}) error
注册时只要参数或返回值不对,server.RegisterTask 就直接 panic,错误信息只有模糊的 invalid task signature,不提示哪一行、哪个函数。
- 不能多返回值:
func(interface{}) (string, error)❌ - 不能少 error:
func(interface{})❌ - 不能参数不是
interface{}:func(string) error❌ - worker 收到 payload 后要自己类型断言,比如
args := payload.(map[string]interface{}),记得加 panic 防御或用ok判断
发送任务时参数必须 JSON 可序列化,且 Args 字段要按规范构造
SendTaskWithContext 不校验参数类型,传错就静默丢弃——你发了,worker 根本收不到。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 支持:
string、int、map[string]interface{}、带json:tag 的 struct - 不支持:
time.Time(会 panic),改用Unix()或Format("2006-01-02T15:04:05Z") -
[]int{1,2,3}要先转成[]interface{},否则序列化为空数组或 panic - 别用
map[interface{}]interface{},JSON encoder 不支持 key 是 interface{} - 构建
tasks.Arg时,Type字段必须是 Go 类型名字符串,如"string"、"float64",不能写"[]byte"或自定义 type 别名
延迟和重试必须手动设 ETA / RetryCount,且默认完全不生效
machinery 不提供“5秒后执行”这种相对时间接口,也不默认重试——哪怕任务 panic,只要没设 RetryCount,就只执行一次。
- 延迟靠
ETA字段,填 Unix 时间戳(秒级),不是 duration;误写time.Now().Add(5 * time.Second).Unix()在时区错或系统时间不同步时,可能立刻触发或永不触发 - 重试需同时设
RetryCount和RetryTimeout(单位秒),例如RetryCount: 3,RetryTimeout: 60 - 重试状态不持久化:worker 重启后,正在重试中的任务会丢失;如需强保障,得自己加幂等 key + 主动查 backend 状态
最容易被忽略的是:worker 启动时不连 broker,也不校验配置是否合法,直到真正消费时才发现连不上——所以每次上线前,先用 redis-cli -u $BROKER_URL ping 或 curl -I $AMQP_URL 手动测通。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










