Go诊断工具gops

好久没写博客了,最近遇到个小坑,特此记录一下。

大家都知道gops是一个列出和诊断Go进程的工具, 它的使用命令如下:

1
2
gops <cmd> <pid|addr> ...
gops <pid> 列出进程信息(包括非Go的进程)

cmd 主要有以下几个

1
2
3
4
5
6
7
8
9
10
stack       	打印当前调用栈
gc 立即运行gc(会一直阻塞直到成功)
setgc 设置GC百分比
memstats 打印内存信息统计
version 打印运行程序go版本
stats 打印运行时信息统计.

trace trace 5s 然后运行go tool trace
pprof-heap 读取堆内存剖析信息然后运行go tool pprof
pprof-cpu 读取cpu剖析信息然后运行go tool pprof

gops支持进程id和远程两种方式

使用时只需要在go程序中嵌入agent即可

1
2
3
4
5
6
7
8
import (
"log"

"github.com/google/gops/agent"
)
if err := agent.Listen(agent.Options{}); err != nil {
log.Fatal(err)
}

本地方式

如上代码启动时会在localhost监听一个随机端口,本地调试时使用gops <cmd> <pid>这些命令完全够用了。

远程方式

由于我们的服务全部跑在容器里,这样上面的gops需要改成远程的方式使用gops <cmd> <remote_addr>

然而就是在这里遇到问题了,默认的Options使用的addr只监听了lo网卡,也就是必须要在容器内才能执行gops,由于是线上环境,开发没有权限登到容器中执行这些,所以需要修改addr 监听所有网卡的指定端口如0.0.0.0:8001。再通过k8s的网络,只要在集群中任意一台节点上就可以使用远程调试了。

然而开发可用的跳板机上没有gops,我们把二进制文件拷贝到跳板机上后执行stack memstats这些信息已经没有问题了,但是在执行profiling相关的命令是总是不成功, 以trace为例,执行生成了trace文件后就结束了

1
2
3
./gops trace 10.244.16.224:8001
Tracing now, will take 5 secs...
Trace dump saved to: /tmp/trace371893560

正常还有类似这样的步骤日志

1
2
3
Parsing trace...
Splitting trace...
Opening browser. Trace viewer is listening on http://127.0.0.1:44365

通过查看gops help 看到trace命令的说明,生成了trace文件后会调用go tool trace命令,从gops源码也看到了这一点

If go tool chain not found, stopping here and keep trace file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//cmd.go
func trace(addr net.TCPAddr, _ []string) error {
fmt.Println("Tracing now, will take 5 secs...")
out, err := cmd(addr, signal.Trace)
if err != nil {
return err
}
if len(out) == 0 {
return errors.New("nothing has traced")
}
tmpfile, err := ioutil.TempFile("", "trace")
if err != nil {
return err
}
if err := ioutil.WriteFile(tmpfile.Name(), out, 0); err != nil {
return err
}
fmt.Printf("Trace dump saved to: %s\n", tmpfile.Name())
// If go tool chain not found, stopping here and keep trace file.
if _, err := exec.LookPath("go"); err != nil {
return nil
}
defer os.Remove(tmpfile.Name())
cmd := exec.Command("go", "tool", "trace", tmpfile.Name())
cmd.Env = os.Environ()
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}

原来忘记跳板机上没有go了,反正要在浏览器上看,索性把文件拉到本地来看了

1
2
3
4
go tool trace -http=:6060 trace371893560
2021/03/25 16:20:19 Parsing trace...
2021/03/25 16:20:19 Splitting trace...
2021/03/25 16:20:19 Opening browser. Trace viewer is listening on http://[::]:6060

pprof-heappprof-cpu也类似,只会生成文件,也同样需要go tool命令来运行。

1
2
$ go tool pprof heap_profile589682544
$ go tool pprof cpu_profile077923742

gerrard wechat
微信扫一扫,订阅我的博客动态^_^
您的支持将鼓励我继续创作!