Heim  >  Artikel  >  Backend-Entwicklung  >  Worker und HTTP-Server wurden ordnungsgemäß heruntergefahren

Worker und HTTP-Server wurden ordnungsgemäß heruntergefahren

WBOY
WBOYnach vorne
2024-02-15 14:48:071031Durchsuche

Worker 和 HTTP 服务器正常关闭

php-Editor Xigua stellt Ihnen in diesem Artikel das normale Herunterfahren von Workern und HTTP-Servern vor. Während des Entwicklungsprozesses ist es sehr wichtig, den Worker und den HTTP-Server ordnungsgemäß herunterzufahren, um die Freigabe von Ressourcen und den normalen Beenden des Programms sicherzustellen. In diesem Artikel wird ausführlich erläutert, wie Worker und HTTP-Server ordnungsgemäß heruntergefahren werden, sowie einige häufig auftretende Probleme und Lösungen. Lassen Sie uns gemeinsam lernen, wie wir das normale Herunterfahren des Servers sicherstellen und die Stabilität und Zuverlässigkeit der Anwendung verbessern können.

Frageninhalt

Ich versuche, einen Arbeitsprozess und einen HTTP-Server zu erstellen, die unabhängig voneinander gestartet werden und auf Beendigung warten und nach Abschluss ordnungsgemäß beendet werden.

Aus irgendeinem Grund startet der Arbeitsthread, aber der http-Server startet erst, wenn das Sigterm-Ereignis gesendet wird. Der http-Server startet erst nach dem Senden des Sigterm-Ereignisses. Was ist das Problem unten?

Ausgabe

https://gosamples.dev is the best
https://gosamples.dev is the best
https://gosamples.dev is the best
^c2023/05/27 15:07:52 listening on http server port:

process finished with the exit code 0

Code

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "sync"
    "syscall"
    "time"
)

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

    go func() {
        signals := make(chan os.Signal, 1)
        signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
        <-signals

        cancel()
    }()

    var wg sync.WaitGroup

    wg.Add(1)
    go func() {
        if err := myWorker(ctx); err != nil {
            cancel()
        }
        wg.Done()
    }()

    wg.Add(1)
    go func() {
        if err := startServer(ctx); err != nil {
            cancel()
        }
        wg.Done()
    }()

    wg.Wait()
}

func myWorker(ctx context.Context) error {
    shouldStop := false

    go func() {
        <-ctx.Done()
        shouldStop = true
    }()

    for !shouldStop {
        fmt.Println("https://gosamples.dev is the best")
        time.Sleep(1 * time.Second)
    }

    return nil
}

func startServer(ctx context.Context) error {
    var srv http.Server

    go func() {
        <-ctx.Done() // Wait for the context to be done

        // Shutdown the server
        if err := srv.Shutdown(context.Background()); err != nil {
            // Error from closing listeners, or context timeout:
            log.Printf("HTTP server Shutdown: %v", err)
        }
    }()

    if err := srv.ListenAndServe(); err != http.ErrServerClosed {
        // Error starting or closing listener:
        return fmt.Errorf("HTTP server ListenAndServe: %w", err)
    }

    log.Printf("Listening on HTTP server port: %s", srv.Addr)

    http.HandleFunc("/readiness", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
    })
    http.HandleFunc("/liveness", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
    })

    return nil
}

Workaround

Wenn ich Ihren Code richtig gelesen habe, starten Sie den Server, bevor Sie den Routenhandler definieren. Das bedeutet, dass der Server beim Starten nichts über Ihre /readiness/liveness Endpunkte weiß, da Sie diese noch nicht hinzugefügt haben. Infolgedessen wird der Server gestartet, führt jedoch keine Aktion aus, da keine Routen verarbeitet werden müssen.

Dann sind Sie nicht dabei http.server 实例中定义 addr 字段。 listenandserve() 使用调用它的 http.server 实例的 addr 字段中定义的地址。如果为空,则默认为 ":http", aber dies ist in Ihrem Code nicht explizit angegeben und kann zu Verwirrung führen.

Ich bin srv.listenandserve ganz ans Ende des Startservers verschoben. Was habe ich verpasst?

Das Problem besteht nicht darin, wo srv.listenandserve 在函数中的位置,而在于如何配置 http.server in der Funktion steht, sondern darin, wie http.server konfiguriert ist und wann der http-Handler eingestellt ist.

Im Originalcode legen Sie den http-Handler fest, nachdem der Server gestartet wurde. Die Handler müssen vor dem Starten des Servers festgelegt werden, da der Server, sobald er ausgeführt wird, keine später definierten neuen Handler mehr aufnimmt.

Und nach der Protokollanweisung log.printf("listening on http server port: %s", srv.addr)位于srv.listenandserve() handelt es sich um einen blockierenden Aufruf. Dies bedeutet, dass die Protokollanweisung erst ausgeführt wird, nachdem der Server gestoppt wurde, weshalb Sie sie erst nach dem Senden des Sigterm-Signals sehen können.

Versuchen Sie, Ihre startserver Funktion wie folgt neu zu organisieren:

func startServer(ctx context.Context) error {
    srv := &http.Server{
        Addr: ":8080", // Define the address where you want the server to listen
    }

    http.HandleFunc("/readiness", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
    })
    http.HandleFunc("/liveness", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(200)
    })

    go func() {
        <-ctx.Done() // Wait for the context to be done

        // Shutdown the server
        if err := srv.Shutdown(context.Background()); err != nil {
            // Error from closing listeners, or context timeout:
            log.Printf("HTTP server Shutdown: %v", err)
        }
    }()

    log.Printf("Listening on HTTP server port: %s", srv.Addr)

    if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
        // Error starting or closing listener:
        return fmt.Errorf("HTTP server ListenAndServe: %w", err)
    }

    return nil
}

In der modifizierten Version der startserver 函数的修改版本中,服务器现在知道您的 /readiness/liveness-Funktion kennt der Server jetzt Ihre
-Endpunkte, da diese vor dem Serverstart definiert wurden. addr HTTP-Handler werden vor dem Serverstart festgelegt und Protokollanweisungen werden vor dem Serverstart gedruckt. Dies sollte Ihr Problem lösen und es dem Server ermöglichen, Anfragen wie erwartet zu starten und zu verarbeiten. Außerdem weiß der Server jetzt, wo er zuhören muss, da

klar definiert ist. 🎜

Das obige ist der detaillierte Inhalt vonWorker und HTTP-Server wurden ordnungsgemäß heruntergefahren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen