本文介绍Go应用监控持续剖析与Go pprof对比。
背景信息
Go pprof 是 Go 语言官方自带的、用于性能分析(Profiling)的强大工具库,在软件开发中,我们经常遇到一些棘手的问题:
程序运行缓慢,CPU 占用率居高不下。
服务运行一段时间后,内存持续增长,最终导致OOM(Out of Memory)。
程序响应变慢,感觉像是被什么东西“卡住”了。
启动了大量的 Goroutine,但它们似乎都没有正常工作。
凭借直觉或日志去猜测问题根源,往往费时费力且不准确。pprof 提供了基于数据的、可视化的方法来回答以下关键问题:
CPU都花时间在哪了? —— 找到消耗计算资源最多的函数。
内存都被谁占用了? —— 找到分配内存最多的对象和代码路径。
程序为什么会被阻塞? —— 分析导致 Goroutine 等待的同步原因(如锁、通道)。
Goroutine都在干什么? —— 查看所有协程的调用栈,定位协程泄露。
pprof 通过采样(Sampling)的方式工作,以较低的开销收集数据。它可以生成多种类型的分析报告(Profile):
CPU Profile (profile): 这是最常用的。它会按固定的频率(默认100Hz,即每秒100次)去“抓拍”当前正在执行的函数的调用栈。通过分析这些样本,就能知道哪些函数占用了最多的 CPU 时间。
Heap Profile (heap): 用于分析程序的内存使用情况。它记录了当前堆上所有存活对象的分配信息,可以帮你找到是哪段代码分配了大量内存并且没有释放。
Goroutine Profile (goroutine): 这是一个当前所有 Goroutine 状态的“快照”。它会显示每个 Goroutine 的数量以及它们各自的调用栈。对于调试 Goroutine 泄露(Goroutine 启动后无法正常退出)非常有帮助。
Block Profile (block): 用于记录导致 Goroutine 阻塞(等待)的同步操作所花费的时间。例如,等待一个未缓冲 channel 的读/写、或等待一个被其他 Goroutine 持有的互斥锁。它可以帮你找到并发程序中的“堵点”。
Mutex Profile (mutex): 专门用于报告互斥锁的竞争情况。它可以告诉你哪些锁的等待时间最长,竞争最激烈。
Trace (trace): 这是一个更强大的工具,它能在一段时间内(如1秒)记录程序执行的几乎所有事件,如 Goroutine 的创建/阻塞/唤醒、系统调用、GC(垃圾回收)等。它会生成一个详细的事件流,用于分析延迟问题和复杂的并发交互。
使用对比
Go Runtime提供了pprof的功能,通过类似以下方式将pprof集成到应用程序中,通过访问应用的6060端口获取到pprof的火焰图等进行分析:
package main
import (
"log"
"net/http"
_ "net/http/pprof" // 关键!匿名导入 pprof 包
)
func main() {
// ... 你的其他业务 handler ...
http.HandleFunc("/work", func(w http.ResponseWriter, r *http.Request) {
// 模拟一些工作
// ...
w.Write([]byte("Work done!"))
})
log.Println("Server started on :6060")
// 启动 HTTP 服务器
// pprof 的 handler 会自动注册到默认的 http.ServeMux
log.Fatal(http.ListenAndServe(":6060", nil))
}相比通过代码集成pprof的方式,Go应用监控的持续剖析功能提供了更多的能力(Golang应用持续剖析):
无需修改代码、占用端口,接入请看(开始监控 Go 应用)。
随开随关,通过配置开启、关闭。

无需其他组件拉取分析,应用监控可直接查看,减少额外工作。

代码热点,将profiling跟Trace关联(使用代码热点诊断Golang应用慢调用问题)。

除了持续剖析外,Go应用监控还提供了无侵入的指标统计、链路追踪等能力,详情请看(监控ACK集群下的Golang应用)。