好久没写博客了,最近遇到个调试线上go服务的小问题,特此记录一下。
大家都知道gops是一个列出和诊断Go进程的工具, 它的使用命令如下:
gops <cmd> <pid|addr> ...
gops <pid> 列出进程信息(包括非Go的进程)
cmd 主要有以下几个
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即可
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文件后就结束了
./gops trace 10.244.16.224:8001
Tracing now, will take 5 secs...
Trace dump saved to: /tmp/trace371893560
正常还有类似这样的步骤日志
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.
//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了,反正要在浏览器上看,索性把文件拉到本地来看了
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-heap
和pprof-cpu
也类似,只会生成文件,也同样需要go tool
命令来运行。
$ go tool pprof heap_profile589682544
$ go tool pprof cpu_profile077923742