Maison  >  Article  >  développement back-end  >  Le processus golang disparaît tout seul

Le processus golang disparaît tout seul

PHPz
PHPzoriginal
2023-05-10 10:14:06799parcourir

Récemment, j'ai rencontré un problème très étrange dans un programme écrit en Golang, c'est-à-dire que le processus a disparu de lui-même. Après quelques dépannages, j'ai trouvé le problème et résumé quelques expériences. Permettez-moi de partager les problèmes et les solutions que j'ai rencontrés ci-dessous.

Description du problème

Notre produit exécute une tâche régulièrement chaque jour. Au cours des derniers jours, j'ai constaté que la tâche s'arrêtait toujours après quelques minutes. J'ai configuré le journal du processus pour qu'il soit sorti dans un fichier, puis j'ai vérifié. le journal. J’ai constaté que le processus ne fonctionnait que pendant quelques minutes, puis disparaissait de lui-même. Cette situation est très étrange, car je n'ai jamais rencontré de problèmes similaires lors du développement et des tests normaux.

Processus de dépannage

Tout d'abord, j'ai pensé à la solution la plus simple : ajouter des informations de débogage au code. Ainsi, lorsque j'ai démarré le processus, j'ai généré un journal start, puis chaque fois que j'ai effectué des opérations importantes, j'ai généré un journal correspondant. Ensuite, j'ai redémarré la tâche, j'ai attendu qu'elle s'arrête, puis j'ai vérifié le journal et j'ai constaté que le processus s'était arrêté quelques minutes seulement après son démarrage, mais il n'avait généré aucun message d'erreur dans le journal. Il semblait qu'il s'était terminé. lui-même. 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

Ensuite, j'ai essayé d'utiliser la commande strace pour tracer les appels système du processus et voir pourquoi il s'est terminé. Cependant, la structure de ce processus est relativement complexe, avec plusieurs goroutines exécutées. J'ai utilisé la commande strace pour tracer l'une des goroutines (ndeliver) afin de voir ses appels système. Voici le code pertinent de la goroutine ndeliver :

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

// 代码片段

La fonction de ce code est d'enregistrer une fonction de traitement du signal pour le processus et de démarrer une goroutine pour exécuter le server.Start() fonction , cette fonction se bloquera jusqu'à la fin du processus.

Grâce à la commande strace, j'ai découvert que cette goroutine n'avait aucune exception et qu'elle s'est terminée sans rencontrer d'erreur. Cependant, j'ai découvert qu'il y avait d'autres goroutines dans le processus. J'ai continué à utiliser la commande strace pour tracer l'une des goroutines. Ensuite, j'ai trouvé le problème. n’a pas été résolu, donc tout le processus se bloque.

Solution

En regardant le code, j'ai découvert que cette panique était causée par la suppression d'un fichier, mais notre code n'a pas géré cette erreur. Lorsqu'une panique goroutine n'est pas gérée, l'ensemble du processus plante, c'est pourquoi le processus disparaît de lui-même.

Afin de résoudre ce problème, nous devons gérer la panique pour éviter qu'elle ne fasse planter tout le processus. Nous pouvons utiliser la fonction de récupération si nécessaire pour capturer la panique, puis la gérer pour éviter un crash du processus.

Ce qui suit est un exemple de code pour gérer la panique :

rrreee

En utilisant la fonction defer, lorsque la goroutine se termine, même si elle panique, nous pouvons la capturer et la gérer en conséquence. Ici, nous générons simplement les informations de panique, mais en réalité. , nous pouvons également effectuer d'autres traitements ici, comme envoyer une alerte ou enregistrer plus d'informations sur l'erreur. 🎜🎜Résumé🎜🎜Lors de l'écriture de code Golang, en raison de la nature particulière de la goroutine, lorsqu'une goroutine panique, cela peut provoquer le crash de l'ensemble du processus. Par conséquent, lors de l’écriture du code, nous devons prendre en compte cette situation et écrire du code pour gérer cette situation. Il est très important d’ajouter la gestion de la panique dans le code, cela peut nous aider à éviter de rencontrer des problèmes similaires dans l’environnement de production. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:carte du Golang à découperArticle suivant:carte du Golang à découper