【问题标题】:Infinite loop channel operation cause high CPU usage无限循环通道操作导致高 CPU 使用率
【发布时间】: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。
  • 好吧,你的代码显示的不够多,记住最小的可重现示例......

标签: go cpu channel


【解决方案1】:

最后,我发现当添加通道逻辑时,该逻辑会将一些数据添加到服务器中其他代码会频繁序列化/反序列化它们的地方。那就是吃CPU的地方。 因此,CPU增加与无限Channel逻辑无关

【讨论】:

    猜你喜欢
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多