>  기사  >  백엔드 개발  >  golang 프로세스가 저절로 사라집니다.

golang 프로세스가 저절로 사라집니다.

PHPz
PHPz원래의
2023-05-10 10:14:06796검색

최근 Golang으로 작성된 프로그램에서 프로세스가 저절로 사라지는 아주 이상한 문제에 직면했습니다. 문제를 해결한 후 문제를 발견하고 몇 가지 경험을 요약했습니다. 아래에서 제가 겪은 문제와 해결책을 공유하겠습니다.

문제 설명

저희 제품은 매일 정기적으로 작업을 실행하는데, 지난 며칠간 작업이 항상 몇 분 후에 중지되는 것을 발견했습니다. 프로세스 로그를 파일로 출력하도록 설정한 후 확인했습니다. 나는 그 프로세스가 몇 분 동안만 실행되다가 저절로 사라진다는 것을 발견했습니다. 이 상황은 매우 이상합니다. 왜냐하면 일반적인 개발 및 테스트에서 비슷한 문제가 발생한 적이 없기 때문입니다.

문제 해결 과정

우선 가장 간단한 해결책을 생각했습니다. 코드에 디버그 정보를 추가하는 것입니다. 그래서 프로세스를 시작하면 start 로그를 출력하고, 중요한 작업을 수행할 때마다 해당 로그를 출력합니다. 그런 다음 작업을 다시 시작하고 중지될 때까지 기다렸다가 로그를 확인한 결과 프로세스가 시작된 지 몇 분 만에 중지되었으나 로그에 오류 메시지가 출력되지 않은 것으로 나타났습니다. 그 자체. start 的 log,然后每执行一些重要的操作,再输出一条相应的 log。然后,我重新启动了任务,等待它停止,然后查看 log,发现进程刚启动了几分钟就停止了,但是它在 log 中没有输出任何错误信息,似乎它就是自己终止了。

接着,我尝试使用 strace 命令来跟踪进程的系统调用,看看它终止的原因。但是,这个进程的结构比较复杂,有多个 goroutine 在运行。我使用了 strace 命令来跟踪其中的一个 goroutine(ndeliver),看看它的系统调用情况。以下是 ndeliver goroutine 的相关代码:

c := make(chan os.Signal, 1)

signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)

go func() {
    sig := <-c
    log.Errorf("main: received signal %s, shutting down server", sig.String())
    server.Stop()
    os.Exit(0)
}()

go func() {
    err := server.Start()
    if err != nil {
        log.Fatalf("ndeliver: server start error: %s", err)
    }
}()

这段代码的作用是为进程注册信号处理函数,并启动一个 goroutine 来执行 server.Start() 函数,该函数会一直阻塞直到进程退出。

通过 strace 命令,我发现这个 goroutine 没有任何异常,它也没有遇到什么错误就退出了。但是,我发现进程中还有其他的 goroutine,我继续使用 strace

다음으로, strace 명령을 사용하여 프로세스의 시스템 호출을 추적하여 종료 이유를 확인해 보았습니다. 그러나 이 프로세스의 구조는 여러 고루틴이 실행되므로 상대적으로 복잡합니다. 나는 시스템 호출을 보기 위해 고루틴(ndeliver) 중 하나를 추적하기 위해 strace 명령을 사용했습니다. 다음은 ndeliver 고루틴 관련 코드입니다.

defer func() {
    if r := recover(); r != nil {
        log.Errorf("goroutine panic: %v", r)
        // TODO: 处理 panic
    }
}()

// 代码片段

이 코드의 기능은 프로세스에 대한 신호 처리 기능을 등록하고 고루틴을 시작하여 server.Start()를 실행하는 것입니다. 함수, 이 함수는 프로세스가 종료될 때까지 차단됩니다.

strace 명령을 통해 이 고루틴에는 예외가 없으며 오류도 발생하지 않고 종료되었음을 확인했습니다. 그러나 그 과정에서 다른 고루틴이 있다는 것을 발견했습니다. 계속해서 strace 명령을 사용하여 고루틴 중 하나를 추적했는데, 문제가 발생하여 패닉이 발생했습니다. 처리가 해결되지 않아 전체 프로세스가 중단됩니다.

해결책

코드를 살펴보면 파일 삭제로 인해 이러한 패닉이 발생한 것을 발견했지만 우리 코드에서는 이 오류를 처리하지 못했습니다. 고루틴 패닉이 처리되지 않으면 전체 프로세스가 충돌하므로 프로세스가 저절로 사라집니다.

이 문제를 해결하려면 전체 프로세스가 중단되지 않도록 패닉을 처리해야 합니다. 패닉을 포착한 다음 프로세스 충돌을 방지하기 위해 처리하는 데 필요한 복구 기능을 사용할 수 있습니다.

다음은 패닉 처리를 위한 코드 예제입니다.

rrreee

defer 함수를 사용하면 고루틴이 종료될 때 패닉이 발생하더라도 이를 캡처하여 그에 따라 처리할 수 있지만 실제로는 패닉 정보를 출력합니다. , 경고를 보내거나 오류에 대한 추가 정보를 기록하는 등의 다른 처리도 여기에서 수행할 수 있습니다. 🎜🎜요약🎜🎜Golang 코드를 작성할 때 고루틴의 특수한 특성으로 인해 고루틴 패닉이 발생하면 전체 프로세스가 중단될 수 있습니다. 따라서 코드를 작성할 때 이러한 상황을 고려하고 이러한 상황을 처리할 수 있는 코드를 작성해야 합니다. 코드에 패닉 처리를 추가하는 것이 매우 중요합니다. 이는 프로덕션 환경에서 유사한 문제가 발생하는 것을 방지하는 데 도움이 될 수 있습니다. 🎜

위 내용은 golang 프로세스가 저절로 사라집니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.