【发布时间】:2021-11-10 21:10:19
【问题描述】:
我有一个要求,我需要定期做多项事情(此处无关)。我使用下面提到的代码块实现了它-
func (processor *Processor) process() {
defaultTicker := time.NewTicker(time.Second*2)
updateTicker := time.NewTicker(time.Second*5)
heartbeatTicker := time.NewTicker(time.Second*5)
timeoutTicker := time.NewTicker(30*time.Second)
refreshTicker := time.NewTicker(2*time.Minute)
defer func() {
logger.Info("processor for ", processor.id, " exited")
defaultTicker.Stop()
timeoutTicker.Stop()
updateTicker.Stop()
refreshTicker.Stop()
heartbeatTicker.Stop()
}()
for {
select {
case <-defaultTicker.C:
// spawn some go routines
case <-updateTicker.C:
// do something
case <-timeoutTicker.C:
// do something else
case <-refreshTicker.C:
// log
case <-heartbeatTicker.C:
// push metrics to redis
}
}
}
但我注意到每隔一段时间,我的 for select 循环就会在某处卡住,我似乎无法找到位置或原因。 卡住是指我停止接收刷新代码日志。但它会在一段时间后(5-10 分钟)再次开始正常工作
我已确保每个代码中的所有操作都在极短的时间内完成(约 0 毫秒,通过放置日志进行检查)。
我的问题:
- 在单选中使用多个代码是一种良好/正常的做法(老实说,我在网上没有找到很多使用多个代码的示例)
- 任何知道任何已知问题/陷阱的人都可以在这些问题/陷阱中长时间阻塞循环。
感谢任何帮助。谢谢
【问题讨论】:
-
根据您提供的信息,最可能的原因是其中一个案例花费的时间比您预期的要长。
-
让所有这些代码由单个
select处理而不是每个代码单独的 goroutine 有什么好处?如果您正在执行一些长时间运行的操作,例如refreshTicker,在此操作完成之前不会处理其他代码。 -
@aquaman 你解决了这个问题吗?我会对原因和解决方案感兴趣。
-
@Juve 是的,我能够解决它。问题在于“case”内部调用的函数之一。我们使用 tickers 定期处理 LRU,在某些情况下 LRU 的实现不正确导致无限循环 :( 修复问题后,ticters 不再有问题 :)
-
很高兴听到@aquaman。我刚刚发布了对您的问题的较长回答,但想等到您确认我的假设。我希望它有助于更好地理解这个主题。
标签: go concurrency ticker