如何使用gocelery模块通过设置ETA调度一次性非周期性任务?
使用gocelery设置10秒ETA的单次任务调度
没问题,我来一步步教你实现这个需求——用gocelery调度一个10秒后执行、仅运行一次的任务,完全不需要周期性配置。
第一步:准备依赖
首先确保你已经安装了gocelery和对应的broker驱动(这里以最常用的Redis为例):
go get github.com/gocelery/gocelery/v2 go get github.com/go-redis/redis/v8
第二步:编写任务生产者(发送任务的代码)
这部分负责把任务发送到broker,并指定10秒后的执行时间(ETA)。核心是用WithETA选项来设置任务的执行时机:
package main import ( "context" "time" "github.com/gocelery/gocelery/v2" "github.com/go-redis/redis/v8" ) func main() { // 初始化Redis客户端(作为任务存储的broker) redisClient := redis.NewClient(&redis.Options{ Addr: "localhost:6379", // 替换成你的Redis地址 }) // 创建gocelery客户端 celeryClient, _ := gocelery.NewCeleryClient( gocelery.NewRedisBroker(redisClient), &gocelery.RedisBackend{Client: redisClient}, 1, // 并发数,这里保持默认即可 ) // 计算10秒后的时间作为ETA(建议用UTC时间避免时区偏差) etaTime := time.Now().UTC().Add(10 * time.Second) // 发送任务,指定ETA——这是单次任务,没有任何周期性配置 task, err := celeryClient.ApplyAsync( context.Background(), "my_delayed_task", // 任务名称,要和消费者端保持一致 []interface{}{"hello from delayed task"}, // 任务参数 gocelery.WithETA(etaTime), // 关键:设置任务的执行时间点 ) if err != nil { panic(err) } // 打印任务ID方便跟踪 println("任务已发送,ID:", task.ID) }
第三步:编写任务消费者(执行任务的worker)
这部分负责注册任务并启动worker,等待ETA时间到了就执行任务:
package main import ( "context" "fmt" "time" "github.com/gocelery/gocelery/v2" "github.com/go-redis/redis/v8" ) // 定义要执行的任务函数 func myDelayedTask(ctx context.Context, args ...interface{}) (interface{}, error) { message := args[0].(string) fmt.Printf("任务执行时间:%s,收到消息:%s\n", time.Now().UTC().Format(time.RFC3339), message) return "任务执行完成", nil } func main() { // 初始化Redis客户端 redisClient := redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) // 创建gocelery worker celeryWorker, _ := gocelery.NewCeleryWorker( gocelery.NewRedisBroker(redisClient), &gocelery.RedisBackend{Client: redisClient}, 1, // 并发数 ) // 注册任务:名称必须和生产者端的一致 celeryWorker.Register("my_delayed_task", myDelayedTask) // 启动worker,开始监听任务 println("Worker已启动,等待任务执行...") celeryWorker.Start() // 让worker持续运行(实际项目中可以用信号处理实现优雅退出) select {} }
关键注意事项
- 时区问题:gocelery的ETA参数优先使用UTC时间,如果你用本地时区,可能会因为worker/broker的时区差异导致任务执行时间偏差。
- 单次任务确认:这里没有设置任何周期性调度参数(比如
WithSchedule或crontab规则),所以任务只会在指定的ETA时间执行一次,不会重复运行。 - Broker可用性:确保你的Redis服务已经启动并正常运行,否则任务无法被存储和传递。
运行步骤
- 启动Redis服务:
redis-server - 启动worker:
go run worker.go - 运行生产者发送任务:
go run producer.go
之后你会看到worker在10秒后输出任务执行日志,完美实现单次延迟执行的需求!
内容的提问来源于stack exchange,提问作者Vani Polnedi
相关产品推荐
相关产品推荐

