Как добавить после обратного вызова в Gin Framework

Мне нужно выйти из приложения с os.Exit(0) ПОСЛЕ HTTP-запроса полностью завершен. Мое приложение запрашивает другой сервер, если оно нуждается в обновлении, поэтому мне нужно выйти для выполнения самостоятельного обновления с перезагрузкой, но я не хочу прерывать текущий HTTP-запрос.

Когда я пытаюсь выйти в middleware после c.Next() или в конце функции-обработчика браузер выдает ошибку: localhost didn’t send any data,

Как это можно сделать?

1 ответ

Решение

Как вы говорите, ваша программа завершает работу до того, как HTTP-соединение завершится корректно - вам нужно дождаться завершения HTTP-транзакции и затем выйти. К счастью с Go 1.8 http.Server имеет Shutdown метод, который делает то, что вам нужно.

Завершение работы корректно завершает работу сервера, не прерывая активных соединений. Выключение работает, сначала закрывая все открытые прослушиватели, затем закрывая все незанятые соединения, а затем бесконечно ждет, пока соединения вернутся в свободное состояние, а затем завершит работу.

Итак, общий подход будет следующим:

exitChan := make(chan struct{})

// Get a reference to exitChan to your handlers somehow

h := &http.Server{
    // your config
}
go func(){
    h.ListenAndServe() // Run server in goroutine so as not to block
}()

<-exitChan // Block on channel
h.Shutdown(nil) // Shutdown cleanly with a timeout of 5 seconds

А потом exitChan <- struct{}{} в вашем обработчике / промежуточном программном обеспечении, когда требуется выключение.

Смотрите также: Как остановить http.ListenAndServe()

Вы можете обратиться к этому примеру в их репозитории github:
грациозно-выключение

package main

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

    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
        time.Sleep(5 * time.Second)
        c.String(http.StatusOK, "Welcome Gin Server")
    })

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

    go func() {
        // service connections
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("listen: %s\n", err)
        }
    }()

    // Wait for interrupt signal to gracefully shutdown the server with
    // a timeout of 5 seconds.
    quit := make(chan os.Signal)
    signal.Notify(quit, os.Interrupt)
    <-quit
    log.Println("Shutdown Server ...")

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server Shutdown:", err)
    }
    log.Println("Server exiting")
}
Другие вопросы по тегам