systemd 守护的一个使用golang 实现的tcp服务, 这个服务使用了github.com/jinzhu/gorm ,每隔一小时 服务就会被重启一次,毫无头绪,无从下手,哪位大神可指点指点,怎么排查
有疑问加站长微信联系(非本文作者)
systemd 守护的一个使用golang 实现的tcp服务, 这个服务使用了github.com/jinzhu/gorm ,每隔一小时 服务就会被重启一次,毫无头绪,无从下手,哪位大神可指点指点,怎么排查
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
`单行代码`
在容易出错的地方要加上容错的机制,使用panic recover机制抓住错误信息就可以定位问题在哪里,然后再解决问题。 个人觉得常出错的地方有使用了nil的数据、数组越界了是最常见的,另外还有一些不容易发现的比如没有关闭链接之类的。 最好是能上源码,如果不关乎行业机密的话。
panic 在日志里没有发现,有,我写个伪代码吧
上面是我伪代码,非常奇怪,定时重启,一个小时来一下
监控来看并未出现明显异常的内存,或者资源波动在重启的时候
我现在怀疑是不是跟这个gorm有一定的关系,我没有加
_db.DB().SetConnMaxLifetime(time.Hour)
上面这行代码我没有加
自动重启?怎么知道重启的
我记录了一个日志,_db.DB().SetConnMaxLifetime(time.Hour)这个我已经验证过了,跟它没有关系,我加上了以后还是会重启,
另外我日志使用了 gopkg.in/natefinch/lumberjack.v2 来记录的日志
我TCP监听服务在启动的时候会 输入一行日志
类似这样:
logger.Init("PProf").Info("开始启动PProf监控", zap.Reflect("port", port))
我现在在逐步的用最笨的方式,挨个移除模块,现在已经把mysql连接池移除了,观察是否还会重启
刚又出现了,伴随着的大概率就会出现CPU 爆满,刚想用pprof查线下,结果连pprof都异常了,干瞪眼儿了。。。。
如果不确定是不是未捕获的panic导致的话。加个环境变量GOTRACEBACK=crash后运行。这样崩溃后会产生croedump。然后用gdb或dlv还原现场。注意崩溃时内存占用大小,这个和croedump大小有关。
如果不是panic,那么通过dmesg查看系统日志
神奇的现象,我遇到所有go程序重启都会有panic打印,很快就能发现问题。难道说你这个程序时操作系统杀死,go进程内部还没来得急出现panic逻辑么?我觉得你可以捕获一些常用的信号,捕获成功加上打印试试。只要不是
kill -9 pid
这种信号,都可以捕获成功吧。todo里面如果有goroutine,就将goroutine里的代码研究下。因为recover应该是不能抓到子协程的错误的。
1、为了找到原因,笨的方法就是在每个goroutine里加上defer,捕捉recover。 2、避免整个应用宕掉,在goHandleConn(conn)方法里追加defer,捕捉recover,保证for循环不会抛出panic.
goHandleConn伪代码 已经加上了,没有recover到任何信息
我现在只能用最原始,最无脑的办法 就是排除法懵,已经单独启动了一个应用,代码很干净,为了排除日志扩展可能得问题,我临时换了一个扩展,就等结果了,如果一个小时候还会重启,那我就崩塌了,我只能怀疑是systemd有问题,就换个别的守护试试
果然,上面的代码也重启了。。。。
问题已解决,感谢楼上的各位的热心帮助,下面是我得解决方法,确定问题就在于systemd,当启动的时候 虽然日志成功,但是systemd并未收到信号量running,这个时候会启动一个一小时启动一次的方式,这个感兴趣的可以详细的了解