此工具主要是用来采样、分析各链路上的各种指标数据以分析应用性能瓶颈的
默认每 10ms
会采样一次指定指标都数据
采集的这个数据,称为对应指标
的画像数据
下文我们都称之为 profiling
数据
图 1-1
获取的 profiling
数据是动态的
要想获得有效的数据,请保证应用处于较大的负载
(比如正在生成中运行的服务,或者通过其他工具模拟访问压力)
否则如果应用处于空闲状态,得到的结果可能没有任何意义
如果是 API
性能问题
一般可以通过本地使用 wrk 进压测
或者 预发布环境
配合 access_log
进行 流量回放
请注意 pprof
相关接口,在生产环境,请在网关层禁止外部访问
以免被外面的人恶意使用
引入采集路由的功能,本文以 gin
为示例
引入包 net/http/pprof
package http
import (
"github.com/gin-gonic/gin"
"net/http/pprof"
"node_puppeteer_example_go/api/service"
)
var srv *service.Service
func Init(e *gin.Engine, srvInjection *service.Service) *gin.Engine {
srv = srvInjection
//e.Use() // 暂无中间件需要被设置
{
comic := &Comic{}
/**
* 用户端API
* TODO 接口级缓存
*/
routeComic := e.Group("api/")
routeComic.GET("comic/list", comic.GetList)
routeComic.GET("chapter/list", comic.GetChapterList)
routeComic.GET("chapter/detail", comic.GetChapterDetail)
routeComic.GET("image/list", comic.GetImageList)
}
{
// 注入debug信息到router
routerDebug := e.Group("/debug/pprof") // 这个group的命名自定义即可
routerDebug.GET("/", func(c *gin.Context) {
pprof.Handler("index").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/heap", func(c *gin.Context) {
pprof.Handler("heap").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/goroutine", func(c *gin.Context) {
pprof.Handler("goroutine").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/allocs", func(c *gin.Context) {
pprof.Handler("allocs").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/block", func(c *gin.Context) {
pprof.Handler("block").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/threadcreate", func(c *gin.Context) {
pprof.Handler("threadcreate").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/cmdline", func(c *gin.Context) {
pprof.Handler("cmdline").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/profile", func(c *gin.Context) {
pprof.Handler("profile").ServeHTTP(c.Writer, c.Request)
})
routerDebug.Any("/symbol", func(c *gin.Context) {
pprof.Handler("symbol").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/trace", func(c *gin.Context) {
pprof.Handler("trace").ServeHTTP(c.Writer, c.Request)
})
routerDebug.GET("/mutex", func(c *gin.Context) {
pprof.Handler("mutex").ServeHTTP(c.Writer, c.Request)
})
}
return e
}
当然,你也可以看看我在生产环境的集成示例 点此查看
其中我们通常需要观察的几个路由如下
/debug/pprof/profile:访问这个链接会记录 CPU profiling
/debug/pprof/heap: Memory Profiling 的路径,访问这个链接会得到一个内存 Profiling 结果的文件
/debug/pprof/block:block Profiling 的路径
/debug/pprof/goroutines:运行的 goroutines 列表,以及调用关系
采集数据前,先了解各项指标含义
router后缀 | 打点指标介绍 |
---|---|
allocs | 内存分配情况的采样信息 |
blocks | 阻塞操作情况的采样信息 |
cmdline | 显示程序启动命令及参数 |
goroutine | 当前所有协程的堆栈信息 |
heap | 存活对象内存使用情况的采样信息 |
mutex | 锁争用情况的采样信息 |
profile | CPU 占用情况的采样信息 |
threadcreate | 系统线程创建情况的采样信息 |
trace | 程序运行跟踪信息 |
现在发现哪个地方慢就让哪块儿逻辑处于压力状态
比如 API服务
我们发现某个 接口A
慢,就让 接口A
处于压力状态
对于 API
接口,可以直接通过压测尝试复现
本文使用 wrk 作为压测工具
示例场景
我现在认为 漫画列表API
慢
那我就用工具压测吧
条件名 | 对应值 | 备注 |
---|---|---|
线程数 | 8个 | - |
并发连接数 | 50个 | - |
压测时长 | 20分钟 | 主要是想边测边看 |
wrk -t8 -c50 -d 20m 'http://192.168.1.7:8100/api/comic/list?page=1'
调整 http
服务的 writeTimeout
的时间
需要稍微超过采集数据的时间
比如,现在我计划采样 30s
记得多设置几秒,比如我这里多设置 5s
httpServer:
name: node_puppeteer_example_go_api
ip: 0.0.0.0
port: 2333
readTimeout: 3s
writeTimeout: 35s
maxHeaderBytes: 1048576
本次我计划采集的是 内存分配情况
指标数据
2 ~ 5
秒就基本可以满足绝大多数场景了 UI
图,用浏览器展示的时候,会比较卡 pprof
功能最好直接打开,不让外网访问即可,方便快速排查线上问题 依据 profiling
数据,生成SVG
图像文件,方便传阅
下载生成图形的工具 FlameGraph
然后将其解压后的目录加入 环境变量
安装 go-touch
记得找一个有 go.mod
的目录 执行以下命令
go get -v github.com/uber/go-torch
go install github.com/uber/go-torch
理论上,这会安装到 GOPATH
下面的 bin
目录里
所以记得环境变量加下这个目录
示例 linux
系统配置
export PATH=$PATH:$GOPATH/bin
下载 profiling
数据到本地文件 raw.log
curl http://192.168.1.7:8100/debug/pprof/heap?seconds=30 > raw.log
通过 raw.log
生成图像文件 mem.svg
go-torch -b ./raw.log -f mem.svg
生成的文件,如 图 3-1
所示
图 3-1
生成的文件,就是火焰图,如 图 3-2
所示
图 3-2
火焰图含义
X轴
对应指标数据
的百分比 Y轴
CPU
调用方法的先后- 从root
开始一般我们关注 X轴
占比较高的,去优化相关资源消耗问题
如 图 2-1
,中
api/service.(*Service).ComicList
占用的对应资源较高
这时候就可以分析是否为瓶颈
这个过程简单描述下
pprof
工具会先打点下载对应指标的 profiling
数据
然后通过 Web 渲染 UI
展示
通过 pprof
配合图形化工具 graphviz 动态查看
示例在 Ubuntu
上 安装
apt-get install graphviz -y
0.0.0.0:8081
http://192.168.1.7:8100/debug/pprof/heap
30s
GET
参数 seconds
可以设置采集
秒数 go tool pprof -http=0.0.0.0:8081 "http://192.168.1.7:8100/debug/pprof/heap?seconds=30"
等待 30s
后,我们访问下对应地址
为了直观查看数据,选择 Flame Graph
别名 火焰图
,如 图 4-1
图 4-1
评论列表点此评论