golang select 超时处理
time.NewTicker和time.After使用区别
遇到的问题:
前几天升级时,增加了select的超时时间设定,使用的是time.NewTicker方式,但是没有在退出时stop,导致程序运行一段时间后多核机器的cpu全部打满。所以后面专门测试一下下面代码的三种情况,确认原因。(因为网上time.NewTicker这个的时候,很多人写的都没有注意退出时执行关闭操作ticker.Stop)
代码介绍:
1、主要功能是监听mq是否有数据,如果超时时间没有则返回超时异常;
2、实际在测试时,mq是没有数据的。
3、在测试时,是开20个协程测试的;
结论:
1、time.NewTicker如果不在退出时执行:ticker.Stop,会导致cpu越来越高;
2、select监听占用的cpu远远低于日志打印,开启日志打印,会导致cpu有10%,但是不开启打印,cpu大概1%。
所以能减少的打印,尽量减少.
func main(){
dataP :=&MqConnect{}
for{
dataP.GetRecvMsg1(3)
}
return
}
//方式1:time.After监听
func (dataP *MqConnect) GetRecvMsg1(timeout int64) ([]byte, error) {
select {
case <-time.After(time.Second * time.Duration(timeout)):
logs.Info("监听mq超时了:NewTicker.stop:")
return []byte{}, ErrTimeout
case msg, ok := <-dataP.ChanRecvMsg:
logs.Info("收到mq消息:暂时不对chan关闭处理")
return msg.Body, nil
}
}
//方式2:time.NewTicker超时,但是不使用defer ticker.Stop
func (dataP *MqConnect) GetRecvMsg2(timeout int64) ([]byte, error) {
ticker := time.NewTicker(time.Duration(timeout) * time.Second)
//defer ticker.Stop 退出不关闭;
select {
case <-ticker.C:
logs.Info("监听mq超时了:NewTicker.stop:")
return []byte{}, ErrTimeout
case msg, ok := <-dataP.ChanRecvMsg:
logs.Info("收到mq消息:暂时不对chan关闭处理")
return msg.Body, nil
}
}
//方式3:time.NewTicker超时,使用defer ticker.Stop
func (dataP *MqConnect) GetRecvMsg3(timeout int64) ([]byte, error) {
ticker := time.NewTicker(time.Duration(timeout) * time.Second)
defer ticker.Stop 退出不关闭;
select {
case <-ticker.C:
logs.Info("监听mq超时了:NewTicker.stop:")
return []byte{}, ErrTimeout
case msg, ok := <-dataP.ChanRecvMsg:
logs.Info("收到mq消息:暂时不对chan关闭处理")
return msg.Body, nil
}
}