8

定位服务内存泄露和卡死方法(总结)

 1 year ago
source link: https://guonaihong.github.io/post/locating-memory-leaks-and-service-stuck/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

总结一下,也许时间久了,一些方法就忘了。下面的方法都是实战中用过的,各有适用场景。

一、卡死、go程泄露–获取调用栈

1.go build -race编译选项

适用于开发自测,和线上少量灰度。使用简单只要加上-race选项就行。 有线程不安全的代码会打印出调用栈
假如服务端卡死,客户端请求过来,会增加go程,超过4096(记得不是太清楚)的样子,进程就会退出,然后打印所有调用栈 对了,如果是正式上线的服务,需要把-race选项去除
注意 :使用带race选项编译,如果你的服务有问题。进程会退出的。
最佳实践 :对于长期跑的服务,怎么处理race选项,在服务第一个版本上线,可以少量灰度加race选项

go build -race example.go

2. kill -6 pid方式

这个方法不依赖go的工具链,适合手头没有趁手工具,通过发送信号的方式,让进程打印所有调用栈到stdout上。
缺点:会把进程杀死

3. 使用dlv调试

dlv对于golang,就像gdb对于c一样,重要性和位置不言而喻。

go get -u github.com/derekparker/delve/cmd/dlv
  • 挂载到进程里面 dlv的一些命令和gdb类似,以前调试c经常用gdb attach pid挂载到进程看所有线程
dlv attach pid
  • 显示所有协程
goroutines
  • 切换线程 id是通过goroutines 得到的数字
goroutine id
  • 打印当前调用栈
bt

1. ps方式

如果是运行中的进程,把进程名换成你实际的服务名,通过观察ps命令第5列得到虚拟内存, 第6列得到物理内存

ps aux |grep process_name|grep -v grep|awk '{print $5, $6}'

然后导入数据到execl里面画一个曲线,观察下内存趋势。这个方法也适用于c/c++ 然后先观察调用栈,可以回到第一个方法

2. pprof方法

pprof查看内存使用

  • 导入包路径
_ "net/http/pprof"
  • 启动http服务
http.ListenAndServe("localhost:8082", nil)
  • 查看内存使用
go tool pprof http://localhost:8082/debug/pprof/heap

pprof其他用法记录

  • 查看阻塞go程
go tool pprof http://localhost:8082/debug/pprof/block

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK