您的位置:首页 > 编程语言 > Go语言

记一次Golang routine卡死

2016-04-20 10:52 459 查看
Go语言最方便的地方在于可以自由自在的起routine,并且不用自己维护队列。

 

一个很简单的处理模型,针对于长连接活动平凡的链接独立routine进行处理,方便同一连接上下文关联,read routine A讲接收到的消息解包生成消息丢到对应socket的routine B channel中进行处理,routine B在根据不同的任务丢到对应的routine B1或者 routine B2中进行处理,

我们需要一个channel回写routine B1 routine B2的退出信号给你 B 以便B进行响应处理。

那么这么想的话 B 和B1 B2 需要两个channel进行消息通信

伪代码如下,未做友好处理。

var B1 B1Consumer
var B2 B2Consumer

//statch 回写子routine的状态
statch := make(chan StatMsg,1)
B1Ch := make(chan Msg,100)
B2Ch := make(chan Msg,100)
go B1(B1ch,statch)
go B2(B2ch,statch)

for{
select{
case cmsg, ok := <-BCh:
if cmsg.type == B1{
B1ch<-cmsg
}else{
B2ch<-cmsg
}
case StatMsg := <-statch:
deal_state(msg)
}
}


乍一看没什么问题,后面再测试过程中 偶尔发现调用接口没有响应超时。

仔细排查后发现,B1 routine 在退出时回写了一个Done的StatMsg,然后就退出了。

此事Bch还在写数据如果此时B1ch写满了,那么写channel就会卡死,而B1退出的信号已经发送了 不在处理新数据了,那么B routine就会一直卡死在

B1ch<-cmsg

此时已经B routine 已经无法进行下一次select的操作,进而等Bch channel写满 卡死读取routine,等多个读取routine卡死,客户端表现就是无响应了 超时了。

 

找到问题解决办法就简单了。

增加写入channel超时 并且增加statch 的大小

statch := make(chan StatMsg,MAXCHANNELSIZE)

select {
case B1ch <- cmsg:
case <-time.After(time.Duration(CLOSETIMEOUT) * time.Second):

}


 

加大channel大小 避免多次触发超时,如果一旦出现超时,将超时的任务释放掉。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: