Maison  >  Article  >  développement back-end  >  Comment arrêter progressivement un serveur HTTP Go après avoir renvoyé une réponse ?

Comment arrêter progressivement un serveur HTTP Go après avoir renvoyé une réponse ?

DDD
DDDoriginal
2024-10-28 19:12:29153parcourir

How to Gracefully Shut Down a Go HTTP Server After Returning a Response?

Arrêter le serveur HTTP après avoir renvoyé une réponse

Dans ce scénario, vous avez créé un robot de ligne de commande Go qui interagit avec l'API Instagram. Pour obtenir le jeton d'accès, vous démarrez un serveur HTTP local pour capturer l'URI de redirection. Cependant, vous rencontrez un problème lorsque vous tentez d'arrêter manuellement le serveur après avoir récupéré le jeton d'accès.

Problème :

Des erreurs « Serveur fermé » et « Adresse mémoire non valide » se produisent lors de l'arrêt du serveur. Serveur

Analyse :

Les erreurs que vous rencontrez indiquent que le serveur HTTP est arrêté prématurément avant que toutes les connexions ne soient fermées correctement. Cela peut se produire en raison d'un comportement asynchrone du gestionnaire HTTP et du processus d'arrêt du serveur.

Solution 1 : Utilisation de Context.WithCancel :

Envisagez d'utiliser context.WithCancel pour créer un contexte pouvant être annulé. lorsque le jeton d'accès est récupéré. Transmettez ce contexte au gestionnaire HTTP et utilisez CancelFunc pour arrêter le serveur en douceur lorsque le contexte est fermé.

<code class="go">package main

import (
    "context"
    "io"
    "log"
    "net/http"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Bye\n")
        cancel()
    })
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hi\n")
    })

    srv := &http.Server{Addr: ":8080"}
    go func() {
        err := srv.ListenAndServe()
        if err != http.ErrServerClosed {
            log.Println(err)
        }
    }()

    <-ctx.Done()

    err := srv.Shutdown(context.Background())
    if err != nil {
        log.Println(err)
    }

    log.Println("done.")
}</code>

Solution 2 : Utiliser le même contexte pour toutes les fonctions :

Vous pouvez également utiliser le même contexte sur plusieurs gestionnaires HTTP et la fonction principale pour garantir que toutes les fonctions sont averties lorsque le serveur doit s'arrêter.

<code class="go">package main

import (
    "context"
    "io"
    "log"
    "net/http"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hi\n")
    })
    http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Bye\n")
        cancel()
    })
    srv := &http.Server{Addr: ":8080"}
    go func() {
        if err := srv.ListenAndServe(); err != nil {
            log.Printf("Httpserver: ListenAndServe() error: %s", err)
        }
    }()
    <-ctx.Done()

    if err := srv.Shutdown(ctx); err != nil && err != context.Canceled {
        log.Println(err)
    }
    log.Println("done.")
}</code>

Conclusion :

En utilisant context.WithCancel ou en passant le même contexte pour plusieurs fonctions, vous pouvez vous assurer que le serveur HTTP s'arrête correctement une fois toutes les connexions fermées. Cela évitera les erreurs que vous rencontrez actuellement.

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