分享
  1. 首页
  2. 文章

一次golang程序无故频繁重启的问题

天地一小儒 · · 2540 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

1. 错误日志

监控日志

程序启动时会打印进程号,同时有系统signal信号捕捉程序,会将程序退出的所有能捕捉的信号都捕捉并打印,然后退出。

1.1不能被捕捉的信号

SIGKILL 9 Term 无条件结束程序(不能被捕获、阻塞或忽略)
SIGSTOP 17,19,23 Stop 停止进程(不能被捕获、阻塞或忽略)

第一个就是我们常见的kill -9 pid

2. 排查方式

1.1 查看日志

日志中加入了捕捉信号量的程序,会将程序退出的所有能捕捉的信号都捕捉并打印,然后退出

// for build -ldflags
var (
 // explain for more details: https://colobu.com/2015/10/09/Linux-Signals/
 // Signal selection reference:
 // 1. https://github.com/fvbock/endless/blob/master/endless.go
 // 2. https://blog.csdn.net/chuanglan/article/details/80750119
 hookableSignals = []os.Signal{
 syscall.SIGHUP,
 syscall.SIGUSR1,
 syscall.SIGUSR2,
 syscall.SIGINT,
 syscall.SIGTERM,
 syscall.SIGTSTP,
 syscall.SIGQUIT,
 syscall.SIGSTOP,
 syscall.SIGKILL,
 }
 defaultHeartbeatTime = 1 * time.Minute
)
func handleSignal(pid int) {
 // Go signal notification works by sending `os.Signal`
 // values on a channel. We'll create a channel to
 // receive these notifications (we'll also make one to
 // notify us when the program can exit).
 sigs := make(chan os.Signal, 1)
 done := make(chan bool, 1)
 // `signal.Notify` registers the given channel to
 // receive notifications of the specified signals.
 signal.Notify(sigs, hookableSignals...)
 // This goroutine executes a blocking receive for
 // signals. When it gets one it'll print it out
 // and then notify the program that it can finish.
 go func() {
 sig := <-sigs
 logs.Info("pid[%d], signal: [%v]", pid, sig)
 done <- true
 }()
 // The program will wait here until it gets the
 // expected signal (as indicated by the goroutine
 // above sending a value on `done`) and then exit.
 for {
 logs.Debug("pid[%d], awaiting signal", pid)
 select {
 case <-done:
 logs.Info("exiting")
 return
 case <-time.After(defaultHeartbeatTime):
 }
 }

通过错误日志可以看到,捕捉不到,所以基本上可以推测,应该是信号SIGKILL或SIGSTOP的问题。

1.2 strace监控当前进程

命令:strace -T -tt -e trace=all -p pid,我当时监控时pid是39918,最后等待了一段时间,果然捕捉到了程序异常退出的信号

strace

但这只能确认这是SIGKILL的问题,具体什么原因,还是无法得知。

1.3 Taming the OOM killer

既然是SIGKILL,那很有可能是OOM的问题,所以我试了一下demsg命令:dmesg -T | grep -E -i -B100 pid,pid是39918。

dmesg

果然,真的是Out Of Memory 错误。

1.4 go tool pprof

我部署的web框架是beego,它本身自带嵌入了golang的调试程序,只需要在app.conf中设置AdminPort = 8098属性就可以,我设置的端口是8098。它还有个监控界面,可以直接在浏览器访问,还是很方便。

beego-admin

不过由于服务器在云端,没有开通这个端口,开通要走很多程序,麻烦,那算了,直接监控了把文件下载到本地查看,命令curl http://localhost:8098/prof?command=get%20memprof,之后,在你的程序的根目录下,就会生成一个mem-xxxx.memprof的文件。

memprof

把这个文件下载到本地,使用命令go tool pprof bdms mem-43964.memprof查看。后来果然发现一个程序没有关闭sql连接,导致大量的内存占用。pprof的教程我就不贴了,推荐一个链接自己看吧。今天就到这里吧。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:天地一小儒

查看原文:一次golang程序无故频繁重启的问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2540 次点击
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏