Graceful 재시작과 정지
웹 서버를 graceful 재시작 혹은 정지를 하고 싶습니까? 이 작업을 하기 위한 몇 가지 방법이 있습니다.
fvbock/endless를 사용하여 기본 ListenAndServe
를 바꿀 수 있습니다. 자세한 내용은 이슈 #296를 참조하세요.
router := gin.Default()
router.GET("/", handler)
// [...]
endless.ListenAndServe(":4242", router)
endless의 대안은 다음과 같습니다:
- manners: A polite Go HTTP server that shuts down gracefully.
- graceful: Graceful is a Go package enabling graceful shutdown of an http.Handler server.
- grace: Graceful restart & zero downtime deploy for Go servers.
만약 Go 1.8을 사용한다면, 이 라이브러리를 사용할 필요가 없습니다! Graceful 종료를 위해 http.Server에 포함되어 있는 Shutdown() 메소드를 사용할 것을 검토해보세요. 자세한 내용은 Gin의 graceful-shutdown 예제에서 확인해 주세요.
// +build go1.8
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"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() {
// 서비스 접속
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen: %s\n", err)
}
}()
// 5초의 타임아웃으로 인해 인터럽트 신호가 서버를 정상종료 할 때까지 기다립니다.
quit := make(chan os.Signal, 1)
// kill (파라미터 없음) 기본값으로 syscanll.SIGTERM를 보냅니다
// kill -2 는 syscall.SIGINT를 보냅니다
// kill -9 는 syscall.SIGKILL를 보내지만 캐치할수 없으므로, 추가할 필요가 없습니다.
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-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)
}
// 5초의 타임아웃으로 ctx.Done()을 캐치합니다.
select {
case <-ctx.Done():
log.Println("timeout of 5 seconds.")
}
log.Println("Server exiting")
}