Метод http.Server.Shutdown

Метод http.Server.Shutdown обеспечивает корректное завершение работы HTTP сервера. Он позволяет серверу дождаться завершения всех активных запросов, прежде чем остановиться. В первый параметр метод принимает контекст, который определяет максимальное время ожидания завершения соединений. Метод возвращает ошибку, если во время завершения работы что-то пошло не так.

Синтаксис

gofunc (srv *Server) Shutdown(ctx context.Context) error

Пример

Давайте создадим HTTP сервер, который корректно завершает работу при получении сигнала прерывания:

gopackage main

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

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
  })

  srv := &http.Server{
    Addr:     ":8080",
    Handler:    mux,
    ReadTimeout:  5 * time.Second,
    WriteTimeout: 10 * time.Second,
  }

  go func() {
    if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
      fmt.Printf("Server error: %v\n", err)
    }
  }()
  fmt.Println("Server started on :8080")

  quit := make(chan os.Signal, 1)
  signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
  <-quit
  fmt.Println("Shutting down server...")

  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()

  if err := srv.Shutdown(ctx); err != nil {
    fmt.Printf("Server shutdown error: %v\n", err)
  }
  fmt.Println("Server gracefully stopped")
}

Результат выполнения кода:

go"Server started on :8080"
"Shutting down server..."
"Server gracefully stopped"

Пример

Рассмотрим ситуацию, когда сервер ожидает завершения активных запросов в течение ограниченного времени:

gopackage main

import (
  "context"
  "fmt"
  "net/http"
  "time"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/slow", func(w http.ResponseWriter, r *http.Request) {
    time.Sleep(5 * time.Second)
    fmt.Fprintf(w, "Slow response")
  })

  srv := &http.Server{
    Addr:  ":8080",
    Handler: mux,
  }

  go func() {
    if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
      fmt.Printf("Server error: %v\n", err)
    }
  }()
  fmt.Println("Server started on :8080")

  time.Sleep(2 * time.Second)

  ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
  defer cancel()

  if err := srv.Shutdown(ctx); err != nil {
    fmt.Printf("Shutdown error: %v\n", err)
  }
  fmt.Println("Server stopped")
}

Результат выполнения кода:

go"Server started on :8080"
"Shutdown error: context deadline exceeded"
"Server stopped"

Смотрите также

  • функцию http.Server.ListenAndServe,
    которая запускает HTTP сервер и начинает прослушивание подключений
  • функцию http.Server.Close,
    которая немедленно закрывает все активные соединения
  • функцию http.Server.Serve,
    которая обслуживает подключения на указанном слушателе
  • функцию http.Server.ListenAndServeTLS,
    которая запускает HTTPS сервер с использованием TLS