Как добавить после обратного вызова в 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")
}