Maison  >  Article  >  développement back-end  >  Comment arrêter l'écoute sur un serveur dans Go

Comment arrêter l'écoute sur un serveur dans Go

王林
王林avant
2024-02-09 12:09:22683parcourir

如何在 Go 中停止监听服务器

Dans le langage Go, comment arrêter gracieusement l'écoute du serveur est une question courante. Lorsque nous devons arrêter le serveur, nous voulons pouvoir fermer correctement toutes les connexions sans affecter le traitement des requêtes. Cet article présentera plusieurs méthodes courantes pour vous aider à résoudre ce problème. Premièrement, nous pouvons utiliser un sémaphore pour contrôler l’arrêt du serveur. Le package os en langage Go fournit une méthode Signal qui peut être utilisée pour capturer les signaux envoyés par le système d'exploitation. Nous pouvons déclencher l'arrêt du serveur en écoutant le signal os.Interrupt, c'est-à-dire Ctrl+C. Dans la fonction de traitement du signal, nous pouvons effectuer certains travaux de nettoyage, comme fermer la connexion à la base de données, sauvegarder les données, etc. Ensuite, appelez la méthode Shutdown du serveur, qui attendra que les requêtes existantes soient traitées avant d'arrêter le serveur. De cette façon, nous pouvons arrêter gracieusement le serveur d’écoute. Il convient de noter que si le serveur ne peut pas être arrêté dans un certain laps de temps, nous pouvons utiliser la méthode WithTimeout dans le package de contexte pour définir un délai d'attente. Une fois ce délai dépassé, le serveur sera forcé de s'arrêter. En utilisant cette approche, nous pouvons garantir que le serveur s'arrête correctement en toutes circonstances. En plus d'utiliser des sémaphores, nous pouvons également utiliser une variable de type booléen pour contrôler l'arrêt du serveur. Lorsque le serveur démarre, nous pouvons définir une variable booléenne globale, telle que isShutdown. Ensuite, dans la fonction qui gère la requête, nous pouvons vérifier la valeur de cette variable, et si elle est vraie, revenir immédiatement et arrêter de traiter la requête en cours. Lors de l'arrêt du serveur, nous définissons isShutdown sur true, puis attendons que toutes les demandes soient traitées avant de quitter le programme. Cette méthode est relativement simple, mais nécessite l'ajout de jugements logiques supplémentaires à la fonction qui gère la requête, ce qui peut légèrement affecter les performances. Pour résumer, que ce soit en utilisant un sémaphore ou une variable booléenne, nous pouvons implémenter la fonction d'arrêt progressif du serveur d'écoute dans le langage Go. La méthode à choisir dépend de vos besoins spécifiques et de la complexité de votre projet

Contenu de la question

J'ai essayé de trouver un moyen d'arrêter gracieusement un serveur d'écoute en cours de route. Parce que listen.accept bloque, il est nécessaire de fermer le socket d'écoute pour signaler la fin, mais je ne peux pas faire la différence entre cette erreur et d'autres erreurs car les erreurs associées ne sont pas exportées.

Puis-je faire mieux ? S'il vous plaît voir fixme中以下代码中的serve()

package main

import (
    "io"
    "log"
    "net"
    "time"
)

// echo server struct
type echoserver struct {
    listen net.listener
    done   chan bool
}

// respond to incoming connection
//
// write the address connected to then echo
func (es *echoserver) respond(remote *net.tcpconn) {
    defer remote.close()
    _, err := io.copy(remote, remote)
    if err != nil {
        log.printf("error: %s", err)
    }
}

// listen for incoming connections
func (es *echoserver) serve() {
    for {
        conn, err := es.listen.accept()
        // fixme i'd like to detect "use of closed network connection" here
        // fixme but it isn't exported from net
        if err != nil {
            log.printf("accept failed: %v", err)
            break
        }
        go es.respond(conn.(*net.tcpconn))
    }
    es.done <- true
}

// stop the server by closing the listening listen
func (es *echoserver) stop() {
    es.listen.close()
    <-es.done
}

// make a new echo server
func newechoserver(address string) *echoserver {
    listen, err := net.listen("tcp", address)
    if err != nil {
        log.fatalf("failed to open listening socket: %s", err)
    }
    es := &echoserver{
        listen: listen,
        done:   make(chan bool),
    }
    go es.serve()
    return es
}

// main
func main() {
    log.println("starting echo server")
    es := newechoserver("127.0.0.1:18081")
    // run the server for 1 second
    time.sleep(1 * time.second)
    // close the server
    log.println("stopping echo server")
    es.stop()
}

Cela s'imprimera

2012/11/16 12:53:35 Starting echo server
2012/11/16 12:53:36 Stopping echo server
2012/11/16 12:53:36 Accept failed: accept tcp 127.0.0.1:18081: use of closed network connection

Je souhaite masquer le message accept failed, mais je ne veux évidemment pas masquer les autres erreurs que accept peut signaler. Je pourrais bien sûr regarder le test d'erreur pour utilisation d'une connexion réseau fermée mais ce serait vraiment moche. Je pourrais définir un indicateur pour indiquer que je suis sur le point de fermer et d'ignorer l'erreur si elle est définie, je suppose - existe-t-il un meilleur moyen ? accept failed 消息,但显然我不想掩盖 accept 可以报告的其他错误。我当然可以查看 use of closed network connection 的错误测试,但这真的很难看。我可以设置一个标志,表示我即将关闭并忽略错误(如果已设置),我想 - 有更好的方法吗?

解决方法

accept() 调用之后检查循环中的一些“是时候停止”标志,然后从 mainSolution de contournement Vérifiez la présence d'un indicateur « temps d'arrêt » dans la boucle après l'appel accept(), puis retournez-le depuis main, puis connectez-vous

à votre Le port d'écoute pour récupérer le socket du serveur "sans rester bloqué". Ceci est très similaire au vieux 🎜"truc de l'auto-tuyauterie"🎜. 🎜

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer