Post

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-QSend-Q 是否为零,如果不为 0,则说明有阻塞存在,导致数据读写延迟。

6.6 其他

如果上面几个方面都没有问题,但是游戏依然出现卡顿或者延迟的情况,可以考虑分析游戏依赖的服务是否出现问题,比如大厅、redis、中台等。因为 go 协程的特性,当有协程这些请求外部服务阻塞时,会切换到其他协程进行工作,所以无法从火焰图上看到真实的阻塞的耗时情况。

比如压测时,其他游戏也出现延迟、无法登陆等,那很有可能是我们并发请求大厅的数量过高,导致大厅响应延迟,影响了其他游戏。开发服的大厅是 2 核,大概能接受 200+qps,测试服是 4 核,大概 500qps 就会出现很明显的延迟。

This post is licensed under CC BY 4.0 by the author.