我们使用golang编写的线上服务,通常会设置一个golang runtime指标监控,包括goroutine num、gc num、gc pause 等等。最近的一次上线,发现 gc 相关的指标出现异常,gc num 和 gc pause 大幅升高。由于 golang 的 gc 是 stop the world 来做, gc 过多会抢占程序的正常执行时间,甚至影响对外提供的服务,因此暂停了上线,准备先把 gc 的问题修复下。

出问题时的 gc 监控如下:



image.png

其中蓝色曲线表示 gc num,黄色曲线表示 gc pause(单位ms),两个指标都是30s的累计数据。可以看到每30s的pause达到了秒级别。

go tool pprof --alloc_objects http://localhost:xxxx/debug/pprof/heapreflect.Valueencoding/jsonfmt.Sprintreflect.Valueswitch case

image.png
reflect.Value
fmt.Sprint

image.png

继续做性能分析,发现gc大头还是json相关操作。这个应用程序的主要功能就是处理json格式传入的消息,因此除非从 json 库着手改善,否则似乎解决不了问题。BTW,在处理的诸多消息中,有一类消息体占用字节数巨大,是其他消息的十倍以上。尝试取消订阅这类消息,发现gc立即好转,恢复到正常水平。不过,这条路径走不通。

export GOGC=400

image.png

有疑问加站长微信联系(非本文作者)