美文网首页golang开发
记录一次排查k8s集群中go服务不断重启的问题

记录一次排查k8s集群中go服务不断重启的问题

作者: robertzhai | 来源:发表于2022-02-09 22:42 被阅读0次

    背景

    1. 某次晚上上线后,某个k8s服务出现频繁重启的现象,看了阿里云k8s的监控,是由于对应服务的健康检查失败导致k8s不断重新创建pod,然后重启。
    2. 看了下splunk里面的错误日志,由于splunk里面的日志太多,几个同事花了一些时间也没定位到是啥原因,加上太晚就决定然运维对Pod进行了扩容,这样可以减少重启的次数,第二天到公司再排查。
    3. 第二天到公司重新review了下代码,没发现明显问题,后来google了下,可能是fatal error 导致进程退出,进而导致健康检查失败,于是我在main函数里对错误日志做了重定向,代码如下
    // 重定向错误  
    // 调用示例 在main函数中加入 bc_error.RedirectFatal("/opt/go/logs/app_fatal.log")
    func RedirectFatal(logFileName string) {
        if logFileName == "" {
            logFileName = fmt.Sprintf("/opt/go/logs/%d_fatal.log", php.Time())
        }   
       
        logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
        if err != nil {
            PanicLogger.Errorf("服务启动出错:打开异常日志文件%s失败 err:%+v", logFileName, err)
        } else if logFile != nil {
            PanicLogger.Warnf("服务启动成功:打开异常日志文件%s 成功", logFileName)
            // 将进程标准出错重定向至文件,进程崩溃时运行时将向该文件记录协程调用栈信息
            syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
        } else {
            PanicLogger.Warnf("服务启动出错:打开异常日志文件%s 发生不明错误", logFileName)
        }   
    }
    
    1. 然后上线了几个pod,终于捕获到了完整的stack fatal error , 对照代码看了是并发写map 导致了fatal error , 这种是不能revovey的,后来在map的地方加了sync.RWMutex 解决了这个问题,上线后没有重启了

    2. 总结不能被recover的

    • 数据竞争(比如:对map进行并发读写),可以通过golang的编译标记race对代码进行检测是否存在数据竞争(比如:并发读写map)
    • 内存不足
    • 死锁

    参考

    相关文章

      网友评论

        本文标题:记录一次排查k8s集群中go服务不断重启的问题

        本文链接:https://www.haomeiwen.com/subject/bdywqrtx.html