本文重点
Gin结合Cron实现定时任务
需要导入的包
go get "github.com/robfig/cron/v3"
简单介绍
// run the scheduler.. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) run() {
c.logger.Info("start")
// Figure out the next activation times for each entry.
now := c.now()
for _, entry := range c.entries {
entry.Next = entry.Schedule.Next(now)
c.logger.Info("schedule", "now", now, "entry", entry.ID, "next", entry.Next)
}
for {
// Determine the next entry to run.
sort.Sort(byTime(c.entries))
var timer *time.Timer
if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
// If there are no entries yet, just sleep - it still handles new entries
// and stop requests.
timer = time.NewTimer(100000 * time.Hour)
} else {
timer = time.NewTimer(c.entries[0].Next.Sub(now))
}
for {
select {
case now = <-timer.C:
now = now.In(c.location)
c.logger.Info("wake", "now", now)
// Run every entry whose next time was less than now
for _, e := range c.entries {
if e.Next.After(now) || e.Next.IsZero() {
break
}
c.startJob(e.WrappedJob)
e.Prev = e.Next
e.Next = e.Schedule.Next(now)
c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next)
}
case newEntry := <-c.add:
timer.Stop()
now = c.now()
newEntry.Next = newEntry.Schedule.Next(now)
c.entries = append(c.entries, newEntry)
c.logger.Info("added", "now", now, "entry", newEntry.ID, "next", newEntry.Next)
case replyChan := <-c.snapshot:
replyChan <- c.entrySnapshot()
continue
case <-c.stop:
timer.Stop()
c.logger.Info("stop")
return
case id := <-c.remove:
timer.Stop()
now = c.now()
c.removeEntry(id)
c.logger.Info("removed", "entry", id)
}
break
}
}
}
大致看一下源码,实际上也是通过定时器time.NewTimer()来开启定时任务。只不过是封装了一下,很方便,开箱即用。
简单用法
// 先实例化一下
c:=cron.New()
// 每五秒执行一次
c.AddFunc("@every 5s", func() {
fmt.Printf("Every five seconds, %s\n", time.Now().Format("15:04:05"))
})
c.Start()
官方文档
官方链接附上....
实战
封装的定时方法,开启的一个子协程并利用读写锁去操作Map
func DeviceWaitChannel() {
newTime := time.Now().Unix()
//子协程
go func() {
lock.RLock()
defer lock.RUnlock()
for key, value := range deviceMap {
if newTime-value.StartTime > 100 {
println(newTime)
deviceMap[key] = entity.DeviceIpValue{Status: result.CodeFailed}
}
}
}()
time.Sleep(time.Second * 2)
}
本来打算使用time.ticker()来做定时任务,后来试过许多方法发现无法在主协程里面去跑,所以采用Gin+Cron来解决定时任务
启动类写法
func main() {
deviceCron := cron.New()
//每5秒执行一次
_, err2 := deviceCron.AddFunc("@every 5s", func() {
service.DeviceWaitChannel()
})
if err2 != nil {
return
}
deviceCron.Start()
r := gin.New()
r = route.PathRoute(r)
err := r.Run(":8082")
if err != nil {
return
} //监听并在127.0.0.1:8888 上启动服务
}
启动类这块应该有更好的写法....不过暂时能用,后期再CR一下