Pprof 监听
获取 60 秒数据
go tool pprof http://localhost:9999/debug/pprof/profile\?seconds=60
http://localhost:9999/ui/
1.开发一个能够并发且正常游戏的模拟客户端
(我这边有一套比较简陋的代码,支持批量创建玩家、登陆玩家、修改玩家道具,只需要实现跟业务相关的逻辑即可)
2. 在游戏服务器代码中启用 pprof
首先添加 pprof 库, import _ "net/http/pprof"
然后启动 http 监听一个端口 http.ListenAndServe(":9999", nil)
3.启动服务器,并监测服务器的资源使用情况
启动服务器后,使用 ps -aux | grep servername
查找服务器对应的 pid
使用 htop -p pid
监测服务器进程 cpu 和内存的使用情况
使用 iotop -p pid
监测服务器进程磁盘 io 的使用情况
4.用模拟客户端进行压测
建议使用多个实例分批次进行并发压测。比如要压测 500 个玩家,可以分成 5 批 100 个玩家,先登陆第一批玩家,等第一批玩家开始游戏了,再登陆第二批玩家。
这样做的好处,一是可以避免瞬间的高峰把服务器搞挂了。二是能够较为真实的模拟不同玩家在不同时间的操作,可以更好地暴露问题。
5.收集数据
进入压测状态后,使用 go tool pprof http://localhost:9999/debug/pprof/profile
收集服务器的数据。收集 30s 后在进入命令行模式后输入 quit 退出,会生成名为【pprof.servername.samples.cpu.00x.pb.gz】的文件,默认放到$HOME/pprof/下。
此时可以记录相应的峰值 cpu、内存、io 的使用情况
也可以通过游戏客户端登陆进行更为直观的体验,可以发现游戏是否存在卡顿,延迟等问题。
6.问题分析和优化
6.1 CPU 过高
使用 go tool pprof -http=ip:9998 [步骤5中生成的文件]
解读 pprof 文件。
访问对应的端口,可以在 VIEW/Flame Graph
里面看到压测时的火焰图,进而分析耗 CPU 操作。
6.2 内存过高
首先判断是否存在内存泄漏。如果没有泄漏,则分析代码看是否有优化的空间。如果有泄漏,可以使用 valgrind
进行检测。
6.3 io 过高
通过 iostat -x 1
查看 io 是否到达瓶颈。主要看 r/s(每秒完成的读io) w/s(每秒完成的写io) await(平均每次io的等待时间) svctm(平均每次io的服务时间)
6.4 死锁
通过访问服务器监听的端口(以上面为例,为 9999),通过 full goroutine stack dump
分析整个游戏的协程情况,结合代码分析问题。
6.5 链接读写
通过 netstat -nap | head
观察 Recv-Q
和 Send-Q
是否为零,如果不为 0,则说明有阻塞存在,导致数据读写延迟。
6.6 其他
如果上面几个方面都没有问题,但是游戏依然出现卡顿或者延迟的情况,可以考虑分析游戏依赖的服务是否出现问题,比如大厅、redis、中台等。因为 go 协程的特性,当有协程这些请求外部服务阻塞时,会切换到其他协程进行工作,所以无法从火焰图上看到真实的阻塞的耗时情况。
比如压测时,其他游戏也出现延迟、无法登陆等,那很有可能是我们并发请求大厅的数量过高,导致大厅响应延迟,影响了其他游戏。开发服的大厅是 2 核,大概能接受 200+qps,测试服是 4 核,大概 500qps 就会出现很明显的延迟。