Go语言教程之边写边学:如何优雅地处理HTTP服务器关闭

在Go中,可以使用http.服务器的Shutdown() 方法。此方法提供了一种正常关闭服务器的方法,允许服务器在关闭所有连接之前完成任何活动请求的处理。

下面是一个示例代码,演示了如何在Go中正常关闭HTTP服务器:

package main

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

func main() {
    // 创建http服务器实例srv := &http.Server{
        Addr: ":8080",
        Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Simulate a long-running request
            time.Sleep(10 * time.Second)
            w.Write([]byte("Hello, World!"))
        }),
    }

    // 接收信号的通道signalCh := make(chan os.Signal, 1)
    signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)

    // go协程中启动服务go func() {
        log.Printf("Server listening on %s\n", srv.Addr)
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("listen: %s\n", err)
        }
    }()

    // 等待关闭信号sig := <-signalCh
    log.Printf("Received signal: %v\n", sig)

    // 创建超时上下文ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    // 优雅的关闭服务if err := srv.Shutdown(ctx); err != nil {
        log.Fatalf("Server shutdown failed: %v\n", err)
    }

    log.Println("Server shutdown gracefully")
}

在此示例中,我们创建了一个新的HTTP服务器,并在单独的goroutine中启动它。我们还创建了一个接收信号的通道,并等待信号关闭服务器。当收到信号时,我们创建一个超时的上下文,并在服务器上调用Shutdown() 方法。如果服务器在超时后仍在处理请求,它将强制终止所有活动连接。

请注意,如果有任何资源需要在服务器关闭之前清理,则应将它们包含在Shutdown() 函数中。这将确保在服务器终止之前清理它们。