我正在开发一个 Go 微服务,我使用
robfig/cron
包来安排作业,最初想到使用 time.Ticker() 但包让我更容易。
我的问题是如何确保 cron 作业仅注册一次,直到运行的 cron 完成并防止多个 goroutine 同时运行。
这与单例方法不同,
内的代码块必须在前面的 RunProcess 函数完成之前才能运行。RunProcess()
我是 golang 及其约定的新手。 :(
这是我当前实现的简化版本:
package main
import (
"fmt"
"sync"
"time"
"github.com/robfig/cron/v3"
)
var isProcessRunning = false
var mu sync.Mutex
func RunProcess() {
mu.Lock()
defer mu.Unlock()
if isProcessRunning {
fmt.Println("Already Running...")
return
}
isProcessRunning = true
fmt.Println("Running...")
// Simulate work
time.Sleep(15 * time.Second)
isProcessRunning = false
}
func InitCron() {
// Create a new cron scheduler
c := cron.New(cron.WithSeconds())
// Add the task to run every 10 seconds
_, err := c.AddFunc("*/10 * * * * *", RunProcess)
if err != nil {
fmt.Println("Error adding cron job:", err)
return
}
// Start the cron scheduler
c.Start()
// Block indefinitely to keep the cron jobs running
select {}
}
func main() {
InitCron()
}
但是,我注意到,当多次调用 InitCron 时,它可能会创建多个 cron 作业,从而导致轻量级微服务出现并发问题和意外行为。
任何有关如何正确管理此问题的建议或示例将不胜感激。
在 golang 中运行 cron 并尝试阻止 cron 直到第一个 cron 完成
为了确保使用 robfig/cron 包的 Go 微服务中的 cron 作业仅注册一次并且不会同时运行多次,您可以利用 robfig/cron 的内置链接功能。如果前一个实例仍在运行,这将允许您使用作业包装器跳过作业执行。
这是您的实现的修订版本,它使用 robfig/cron 提供的 SkipIfStillRunning 作业包装器:
package main
import (
"fmt"
"time"
"github.com/robfig/cron/v3"
)
func RunProcess() {
fmt.Println("Running...")
// Simulate work
time.Sleep(15 * time.Second)
fmt.Println("Completed...")
}
func InitCron() {
// Create a new cron scheduler with a chain that skips the job if it's still running
c := cron.New(cron.WithSeconds(), cron.WithChain(
cron.SkipIfStillRunning(cron.DefaultLogger),
))
// Add the task to run every 10 seconds
_, err := c.AddFunc("*/10 * * * * *", RunProcess)
if err != nil {
fmt.Println("Error adding cron job:", err)
return
}
// Start the cron scheduler
c.Start()
// Block indefinitely to keep the cron jobs running
select {}
}
func main() {
InitCron()
}