【发布时间】:2019-12-28 04:22:26
【问题描述】:
代码示例如下
var TestChan chan int
func SendDataToChannel(dataIn int){
select {
case TestChan <- dataIn:
return
default:
return
}
}
func HandleChannelData(){
for{
time.Sleep(10 * time.Millisecond)
tmpData := <- TestChan
/*
DoSomething with tmpData, call other server
*/
}
}
func main(){
TestChan = make(chan int)
go HandleChannelData()
/*
Start server
*/
}
场景是,在我的服务器中,每个请求(3-5 千 qps)都会调用 SendDataToChannnel。 HandleChannelData 中的 DoSomething 需要时间来处理,并且它的下游处于 QPS 限制下,所以我只是在 HandleChannelData 中添加了一个 sleep。添加到 Channel 的数据应该是非阻塞的并且可以被丢弃,所以我在那里得到了一个“选择默认”和非缓冲的 Channel。
服务器运行时,CPU使用率无限增加,最终达到95%(4核),而我不得不关闭服务器。我 pprof 服务器获取了火炬图,什么也没找到(没有此通道逻辑的相同分发到同一服务器)
我对 CPU 使用率感到困惑。
【问题讨论】:
-
SendDataToChannel 不应该有一个默认的选择案例,它应该阻塞,直到它可以将数据发送到通道。否则,您要么丢失数据,要么进入繁忙的循环。
-
@Not_a_Golfer 在我的情况下,SendDataIn 应该是非阻塞的,并且数据可以被丢弃,正如我在问题中提到的那样
-
看起来你只是给你的服务器提供了比它可以处理的更多的工作,但是你的代码没有展示你在做什么,所以很难判断。如果您删除所有频道内容会怎样?只需处理请求并跳过 SendDataToChannel。它的行为是否相同?如果是这样(这是我的猜测),那么问题是你的容量已经溢出了。
-
@Not_a_Golfer 服务器工作正常,无需输入和处理频道。 sendDatatoChannel 更像是每个请求的中间件,不会影响服务器的正常逻辑。 handleData 是在服务器启动之前启动的 gorouting。
-
好吧,你的代码显示的不够多,记住最小的可重现示例......