Beego内置Cron模块仅支持分钟级单机调度,适合注册低频非关键后台任务,如每5分钟清理缓存、每小时热重载配置、每天同步静态字典表,不支持秒级、cron表达式解析及热更新。

Beego 自带的 Cron 模块不支持秒级调度,且无法热更新任务,生产环境直接用它跑定时任务容易掉坑里。
Beego 的 Cron 模块到底能干什么
Beego v2.x 内置的 beego.Cron 是一个轻量级单机调度器,底层基于 time.Ticker + 串行执行,只支持「分钟级」粒度(最小单位是 1 分钟),不解析标准 Cron 表达式(比如 "*/5 * * * *" 可以,但 "*/5 * * * * ?" 或带秒字段的会 panic)。它适合启动时注册几个低频、非关键的后台检查任务,比如:
- 每 5 分钟清理一次本地缓存目录
- 每小时读一次配置文件做热重载(需自己实现 diff)
- 每天凌晨同步一次静态字典表(前提是任务执行时间
它没有任务状态持久化、无失败重试、无并发控制,beego.Cron.AddFunc 注册后不可动态增删改——重启服务才生效。
如何正确添加一个 Beego Cron 任务
必须在 beego.Run() 之前注册,否则会被忽略。典型写法如下:
func main() {
beego.BeeLogger.Info("Starting app...")
<pre class="brush:php;toolbar:false;">// ✅ 正确:在 Run 前注册
beego.Cron.AddFunc("@every 5m", func() {
beego.BeeLogger.Info("Running cache cleanup...")
os.RemoveAll("cache/tmp")
})
// ❌ 错误:Run 之后调用无效
// beego.Cron.AddFunc("@hourly", ...)
beego.Run()}
支持的时间格式只有这几种(来自 github.com/beego/beego/v2/core/cron):
-
@every 5s(实际最小生效单位仍是 1 分钟,s被静默截断) @every 2m-
@hourly(等价于@every 1h) -
@daily(等价于@every 24h)
注意:@every 30s 看似合法,但 Beego 会把它当 @every 1m 处理,别被日志误导。
为什么不要在生产环境依赖 Beego Cron 做核心调度
三个硬伤直接决定它不适合关键任务:
- 单点故障:进程挂了,所有任务停止,无自动恢复机制
- 无幂等保障:如果任务执行超时或 panic,下次触发时不会补漏,也不会跳过重复执行
- 无可观测性:不记录执行耗时、成功/失败次数、最近 N 次结果,日志只有
Info级别的一行输出
例如你用 beego.Cron.AddFunc("@every 10m", sendReport) 发日报邮件,某次网络抖动导致 sendReport panic,那这次就彻底丢失,下一次不会补偿,也没法从日志里快速定位是哪次失败。
替代方案:用 gocron 或 robfig/cron 接管调度
如果项目已用 Beego,又需要可靠调度,推荐在 main() 中单独启一个 gocron.Scheduler 实例,和 Beego 生命周期解耦:
beego.Run()
这样既保留 Beego 的路由、ORM、配置能力,又获得:
- 真正的秒级支持(
s.Every(30).Seconds()) - 任务可暂停/恢复/删除(
s.Remove,s.Stop) - 失败自动重试(
.LimitRunsTo(3))、上下文超时控制 - 与 Beego 日志系统共用(
beego.BeeLogger可传给gocron.WithLogger)
真正棘手的是跨节点调度一致性——这时候就得上分布式方案,比如用 Redis 锁 + robfig/cron,或者直接切到 webcron 这类带 UI 的 Beego 生态专用调度器。











