Goroutine泄露问题

背景介绍

某次上线后服务goroutine数量激增,怀疑是goroutine泄露导致,监控如下

分析

本次上线的是一个web接口服务,尝试在线下模拟复现问题
使用wrk压测goroutine数开始上涨,停止wrk后goroutine数未回落
使用pprof查看goroutine profile后发现项目中存在goroutine阻塞情况

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ch, ech := make(chan *bp.PublishResponse), make(chan error)
tryTimes := 2
for i := 0; i < tryTimes; i++ {
go func() {
pubRes, errPub := xxx.Publish(ctx, &publishReq)
if errPub != nil {
ech <- errPub //这里有问题
return
}
ch <- pubRes //这里也有问题
}()
}
for {
select {
case pubRes := <-ch:
return pubRes, nil
case errPub := <-ech:
return nil, errPub
case <-time.After(400 * time.Millisecond):
return nil, fmt.Errorf("publish err: %s", "timeout")
}
}

将传输channel调整为缓冲channel后问题解决

1
ch, ech := make(chan *bp.PublishResponse, 2), make(chan error, 2)

Goroutine泄露

goroutine在channel上发生阻塞或进入死循环导致系统goroutine数越积越多的现象就是goroutine泄露

解决方法

1.使用缓冲channel
2.主动通知终止

扩展

1.如何观测分析goroutine泄露

  • 通过监控工具
  • 通过pprof

参考资料

Goroutine Leak和解决之道