Heim > Artikel > Backend-Entwicklung > Worker und HTTP-Server wurden ordnungsgemäß heruntergefahren
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.
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?
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
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 }
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
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!