我需要在HTTP请求完全完成后用os.Exit(0)
退出应用程序。我的应用程序询问另一台服务器是否需要升级,因此我需要退出以通过重新启动执行自我升级,但我不想破坏当前的HTTP请求。
当我尝试在c.Next()
之后或处理程序函数结束时退出中间件时,浏览器会出错:localhost didn’t send any data
。
如何做到这一点?
答案 0 :(得分:3)
正如您所说,您的程序在HTTP连接完全干净之前终止 - 您需要等待HTTP事务完成然后退出。幸运的是,由于Go 1.8 http.Server
有Shutdown
method可以满足您的需求。
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{}{}
。
答案 1 :(得分:1)
您可以在其github存储库上参考此示例:
graceful-shutdown
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")
}