time.AfterFunc 定时器如何避免程序重启造成的中断
线上不可避免的会重启进程, 一重启这个定时器就没了, 应该有啥解决办法的吧, 不然这个函数 作用就不太高了
time.AfterFunc 定时器如何避免程序重启造成的中断
线上不可避免的会重启进程, 一重启这个定时器就没了, 应该有啥解决办法的吧, 不然这个函数 作用就不太高了
认可 @xiaowei520 的思路。
首先,time.AfterFunc 只是个简单的函数,多长时间执行某个动作这个设定只对当前进程有效,如果异常退出,需要一些恢复机制恢复。而关于如何恢复,这应该是程序员考虑的问题。
为实现恢复,肯定需要将保留现场。可行的方案就是把任务配置到外部存储中,保存任务信息,比如任务标识,执行时间,执行任务类型,状态等等。存储到哪里呢?可以是 xiaowei520 说的 redis,或者 MySQL 也行,当然,如果你有精力的话,也可以自己设计个文件结构来保存任务信息。
这种方式的缺点是,如果任务数比较多,一次加载进来会有性能影响,需要考虑负载均衡。而且,任务都加载在一个进程中容灾能力也不是很好,因为只有一个运行中的程序在处理任务,挂了就不行了。
对于上面说的问题,可以尝试引入一些外部服务,比如带有定时功能的 MQ。这样的话,容错的事情就交给 MQ 实现了。通常很多 MQ 组件都是高可用的,可以配置集群。然后,只要向队列上添加多个 consumer,即可实现负载均衡的效果,如果其中某台机器挂了,还有其他的 consumer 在运行,实现容灾能力。
我在网上找到了 RabbitMQ 实现定时消息的文章,如果有需要,可以看看能否参考一下。[Rabbitmq延迟队列实现定时任务](https://blog.csdn.net/wantnru...)
可以使用https://github.com/DanPlayer/...来解决这个问题
type User struct {
Name string
Age int
}
// check for exception shutdown and restart watch task
err = watch.StartWithCheckRestart(func(c timewatch.Watch) {
fmt.Println(c)
infoMap := c.CustomizedAttributes.(map[string]interface{})
marshal, _ := json.Marshal(infoMap)
var info User
_ = json.Unmarshal(marshal, &info)
fmt.Println(fmt.Sprintf("User struct name: %s", info.Name))
fmt.Println(fmt.Sprintf("User struct age: %d", info.Age))
fmt.Println("do that u want")
})
if err != nil {
fmt.Println(err)
}
var watch = timewatch.Service(timewatch.Options{
Key: "MsgWatch",
Cache: cache.NewRedis(cache.RedisOptions{
Addr: "127.0.0.1:6379",
Password: "",
DB: 0,
}),
OutTimeAct: true,
})
// watch plan add
timer, err := watch.AfterFunc(5*time.Second, timewatch.Watch{
Field: "TestField",
CustomizedAttributes: User{
Name: "Dan",
Age: 20,
}, // could use some self make that u want set attributes in watch.CheckRestart
}, func() {
fmt.Println("plan to func")
})
if err != nil {
fmt.Println(err)
return
}
1 回答1.9k 阅读✓ 已解决
1 回答2.2k 阅读✓ 已解决
2 回答1.5k 阅读✓ 已解决
1 回答1.2k 阅读✓ 已解决
1 回答894 阅读✓ 已解决
1 回答1.5k 阅读
1 回答1.3k 阅读
定时器的话 推荐用 github.com/robfig/cron 应该可以满足你的需求。