Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗goSpHsSd 247 of 280 menu
◀ ▶

Остановка HTTP-сервера в Go

Сервер останавливают через контекст, не обрывая уже идущие ответы. Вместо бесконечного ожидания в главной функции держат значение типа сервера, запускают прослушивание в горутине и вызывают команду остановки с контекстом.

Контекст с коротким сроком или ручной отменой передают в остановку: сервер перестает принимать новые соединения и дожидается завершения текущих. Ошибка ErrServerClosed после остановки считается нормальным исходом, а не сбоем.

Запустим сервер и остановим его через секунду отдельной веткой:

package main import ( "context" "fmt" "log" "net/http" "time" ) func main() { mux := http.NewServeMux() mux.HandleFunc("GET /ping", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "pong") }) srv := &http.Server{Addr: "127.0.0.1:8080", Handler: mux} go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatal(err) } }() go func() { time.Sleep(time.Second) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal(err) } }() select {} }

Через секунду прослушивание завершится, а главная функция остается в ожидании для учебного примера. В рабочей программе вместо пустого select часто ждут сигнал или другую отмену контекста.

Тот же прием с отменой из контекста, созданного в main:

package main import ( "context" "fmt" "log" "net/http" "time" ) func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() mux := http.NewServeMux() mux.HandleFunc("GET /ok", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "ok") }) srv := &http.Server{Addr: "127.0.0.1:8080", Handler: mux} go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatal(err) } }() go func() { time.Sleep(500 * time.Millisecond) cancel() shCtx, shCancel := context.WithTimeout(context.Background(), time.Second) defer shCancel() _ = srv.Shutdown(shCtx) }() <-ctx.Done() fmt.Println("stopped") }

Дан объект сервера с адресом 127.0.0.1:8080 и мультиплексором с маршрутом /ping. Напишите полный main.go: запустите прослушивание в горутине и остановите сервер через контекст с сроком одна секунда после короткой паузы.

Дан следующий код:

err := srv.ListenAndServe() if err != nil { log.Fatal(err) }

Скажите, какую проверку ошибки добавить после штатной остановки сервера.

Дан запущенный сервер без вызова остановки. Скажите, чем завершится программа при закрытии терминала и прерывании процесса по сравнению с Shutdown.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить