NumGoroutine 指标持续上涨,且低峰期未下降,判断出现了 Goroutine 泄漏现象。
image.png
1 . 通过访问线上服务 pprof 暴露出来的 HTTP 接口,拿到当前所有协程的堆栈信息;curl http://「ip:port」/debug/pprof/goroutine?debug=2
2 . 发现存在大量存活时间超过上千分钟的 Goroutine,观察堆栈疑似是 http 连接未释放导致,通过对下图 net.sockets.tcp.inuse(正在使用的tcp socket数量)指标的观察进行了进一步的确认;
下面以本次 case http 服务为例,做简单介绍:
当这两种情况同时发生时,如果上游持有对本服务的连接不进行释放,那么服务端会一直维持这个连接的存在,不进行回收,进而导致协程泄漏;
client上游客户端可能为 GO、Java 等,以下为 GO 语言 http 客户端的空闲连接超时设置;
server
解决
建议启动 http server 尽量用后者,前者虽然简单,但是服务不够健壮;
server
image.png
需要注意的一点是,这个 Goroutine 泄漏问题不止在 http 下会发生,在 thrift、grpc 中也是同样的道理,如果服务端不对连接设置 timeout,某些情况下就会被上游拖死。
一起 goroutine 泄漏问题的排查[1]
内存使用量(mem.rss)居高不下,且低峰期未下降,怀疑发生了内存泄漏现象;
问题来自于 GO 在将内存归还给操作系统时的内存释放策略,详情见官方 issues[2],以下做简单介绍。
(此节内容整理自 压测后go服务内存暴涨[3])
不同策略的释放机制
不同策略的实际差别
不同 GO 版本的释放策略
在 GO1.12~GO1.15 且内核版本 4.5 以上,mem.rss 指标已经无法准确观测服务内存占用;
[1]一起 goroutine 泄漏问题的排查: https://zhuanlan.zhihu.com/p/100740270
[2]issues: https://github.com/golang/go/issues/42330
[3]压测后go服务内存暴涨: http://soiiy.com/go/17114.html
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8