go - 每次定时器完成时运行函数的最有效方法,但有大量定时器(千/百万)
问题描述
我正在运行一项服务,用户上传一个持续时间,并且每次计时器用完时都必须重复执行一个函数。
例如,用户说“每 5 分钟运行一次”,然后此函数必须每 5 分钟运行一次。这是通过 API 完成的。
对于少数计时器,这是微不足道的:
func doEvery(d time.Duration, f func(time.Time)) {
for x := range time.Tick(d) {
f(x) // Run the function every d duration
}
}
我可以在 goroutine 中运行每个计时器,而且效果很好。WaitGroups
我可以使用一些基本和同步功能来启动和停止一切。
但是,如果我有数千或数百万个计时器怎么办?我可以为每一个创建一个 goroutine,但感觉效率很低。这不是二郎。
我应该有多个工作队列,按“延迟”排序,并简单地为更频繁的功能分配更多的工作人员吗?如果计时器未准备好,则将其放回队列中。
这也不理想,因为工作人员忙于等待(弹出,检查时间,推入队列)而不是阻塞直到下一个计时器完成。
也许我可以有某种地图,由剩余的持续时间索引?我不确定这里最好的方法是什么。
解决方案
我最近构建了这种解决方案,用户可以根据他们的间隔设置获得通知。我使用 rabbitMQ 和两个 go 脚本制作了一个工作池模型。一个 go 脚本使用下面的 cron 模块在消息队列中创建作业
https://github.com/robfig/cron
另一个 go 脚本是使用消息队列并采取行动的工作脚本。为了扩展,我正在运行多个工作脚本实例。工作脚本的自动缩放可以通过rabbitMQ中的消息数来完成
推荐阅读
- java - 文件路径不起作用,在奥利奥的服务器中上传文件时?
- javascript - 如何将分钟格式化为小时 - 使用 moment.js
- image - 如何统一设置我的六边形图像蒙版?
- php - 如何在 const TITLENAME = $titlename 之类的类中分配常量?
- sql - Oracle - NVL(col1,col2) 按缓慢排序
- sql - SQL Server 存储过程,用于根据表 2 中的行更新表 1 中的行
- laravel - Laravel 返回错误的响应
- ios - 使用 alamofire 5 Swift 5 将视频上传到服务器
- scala - Databricks:以数据框为参数的函数(SCALA)
- awk - 如何 AWK 仅打印特定项目?