
本文介绍一种轻量、无需额外依赖的方案:复用 go 主程序入口,通过命令行参数区分 web 服务与定时任务,在 heroku scheduler 中直接调用同一二进制文件执行后台作业。
本文介绍一种轻量、无需额外依赖的方案:复用 go 主程序入口,通过命令行参数区分 web 服务与定时任务,在 heroku scheduler 中直接调用同一二进制文件执行后台作业。
Heroku Scheduler 是 Heroku 提供的简易定时任务服务,支持按分钟/小时/天频率执行命令。虽然其文档默认以 Ruby 应用为示例,但 Go 应用同样可无缝集成——关键在于让 Scheduler 能调用一个可执行的、具备明确行为的命令。
核心思路:单二进制多模式
Go 应用无需拆分为多个可执行文件或引入 Ruby 包装脚本。推荐做法是复用 main 函数逻辑,通过 os.Args 判断运行模式:
- 默认无参启动 → 启动 HTTP 服务(Web dyno 行为)
- 携带特定参数启动 → 执行预定义的定时任务(Scheduler 行为)
以下是一个典型实现:
package main
import (
"fmt"
"log"
"net/http"
"os"
"time"
)
func handleHome(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from web dyno!")
}
func runScheduledJob() {
log.Println("✅ Starting scheduled job at", time.Now())
// 在此处编写你的定时逻辑,例如:
// - 清理数据库过期记录
// - 发送邮件通知
// - 调用外部 API 同步数据
log.Println("✅ Scheduled job completed.")
}
func main() {
// 检查是否为 Scheduler 调用(如:./myapp "job:cleanup")
if len(os.Args) > 1 {
switch os.Args[1] {
case "job:cleanup":
runScheduledJob()
return
case "job:notify":
// 可扩展其他任务类型
log.Println("Running notification job...")
return
default:
log.Fatalf("Unknown command: %s", os.Args[1])
}
}
// 默认:启动 Web 服务
http.HandleFunc("/", handleHome)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("? Starting web server on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
配置 Heroku Scheduler
-
安装 Scheduler 插件(如尚未安装):
heroku addons:create scheduler:standard
-
打开 Scheduler 管理界面:
heroku addons:open scheduler
-
添加新任务,输入命令(注意:命令需与构建后的可执行文件名一致):
myapp job:cleanup
✅ myapp 是你 Procfile 中定义的 web: 进程对应的可执行文件名(通常为 go build -o myapp . 生成的文件名)
✅ 不要加 go run —— Scheduler 运行在生产环境,仅执行已编译的二进制文件 设置执行频率(如每小时一次),保存即可。
注意事项与最佳实践
- 构建一致性:确保 go build 输出的二进制文件名与 Scheduler 命令中调用的名称完全一致(推荐在 Makefile 或 heroku-buildpack-go 的 GO_INSTALL_PACKAGE 中统一管理)。
- 环境隔离:定时任务共享应用环境变量(如 DATABASE_URL),务必验证任务逻辑在生产环境下安全可靠。
- 错误处理与日志:任务失败时 Scheduler 不会重试,建议在 runScheduledJob() 中加入 defer 日志、panic 捕获及必要告警(如发送 Slack 通知)。
- 资源限制:Scheduler 任务运行时限为 10 分钟,超时将被强制终止;复杂任务请考虑拆分或迁移到 Worker dyno + Redis Queue。
该方案简洁、可控、零额外依赖,完美契合 Go 的“单一可执行文件”哲学,是中小型 Go 应用在 Heroku 上实现轻量定时调度的推荐实践。











