前言
很多时候后台需要做定时任务的需求,笔者的项目采用go-zero框架微服务框架,需要做定时任务,于是做了如下方法调研,共有大概三种主要选择
方案
难度总体由容易到复杂
go的timer库
通过Go的标准库time
中的Ticker
和Tick
功能来设置和管理定时任务,可以直接集成在服务启动逻辑中,不需要额外的文件或复杂的配置
Go
func startTicker() {
ticker := time.NewTicker(1 * time.Hour) // 每小时执行一次
defer ticker.Stop()
for {
select {
case <-ticker.C:
// 执行定时任务
fmt.Println("执行定时任务...")
// 这里可以放置你的业务逻辑
}
}
}
cron库
使用robfig/cron这个
Go库,作为大型复杂项目的定时任务,cron非常常见也非常强大
大概要在go-zero的服务启动文件里添加如下代码
Go
// 初始化Cron调度器
cronScheduler := cron.New(cron.WithSeconds()) // 使用WithSeconds选项支持秒级调度
// 添加定时任务
_, err := cronScheduler.AddFunc("0 */1 * * * *", func() { // 每分钟执行一次
// 定时任务的逻辑
})
if err != nil {
logx.Errorf("添加定时任务失败: %v", err)
return
}
// 启动Cron调度器
cronScheduler.Start()
// 停止Cron调度器
defer cronScheduler.Stop()
go-queue
这是一种官方更加推荐的方法,不过需要配置消息队列集群,大概代码如下
Go
package main
import (
"fmt"
"strconv"
"time"
"github.com/zeromicro/go-queue/dq"
)
func main() {
producer := dq.NewProducer([]dq.Beanstalk{
{
Endpoint: "localhost:11300",
Tube: "tube",
},
{
Endpoint: "localhost:11301",
Tube: "tube",
},
})
// 延迟 5s 后处理
_, err := producer.Delay([]byte("hello"), time.Second*5)
if err != nil {
fmt.Println(err)
}
// 在指定时间点处理
_, err = producer.At([]byte("hello"), time.Now().Add(time.Second*10))
if err != nil {
fmt.Println(err)
}
}
总结
go-queue的方案直接被笔者排除了,不再额外配置消息队列集群,
其他两个方法比较也很明显
使用Cron库,可以在同一个调度器中管理多个任务,每个任务都有自己的Cron表达式
使用timer,如果有很多不同的任务,需要不同的时间间隔,管理这些会很麻烦
使用timer不需要引入依赖,使用cron需要引入依赖