Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Graceful Shutdown이 적용된 Go HTTP server
FROM golang
LABEL maintainer=tkddlf59@gmail.com
COPY server /usr/bin/server
CMD "server"
FROM golang
LABEL maintainer=tkddlf59@gmail.com
COPY server /usr/bin/server
# 수정된 부분
CMD ["server"]
package main
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
h := &HTTPHandler{}
server := &http.Server{Addr: ":1202", Handler: h}
if err := server.ListenAndServe(); err != nil {
fmt.Printf("error: %v\n", err)
}
}
type HTTPHandler struct{}
func (h *HTTPHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
res.WriteHeader(http.StatusOK)
res.Write([]byte("OK\n"))
}
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
var logger = log.New(os.Stdout, "", log.LstdFlags)
func main() {
h := &HTTPHandler{}
server := &http.Server{Addr: ":1202", Handler: h}
// goroutine으로 서버 실행
go func() {
logger.Println("Start Server...")
if err := server.ListenAndServe(); err != nil {
logger.Printf("error: %v\n", err)
}
}()
// OS SIGNAL을 수신할 chanel 생성
signalChan := make(chan os.Signal, 1)
// KILL, INTERRUPT, QUIT, TERM SIGNAL 수신 등록
signal.Notify(
signalChan,
os.Interrupt,
os.Kill,
syscall.SIGQUIT, // kill -SIGQUIT XXXX
syscall.SIGTERM,
)
// SIGNAL 수신
sig := <-signalChan
logger.Printf("Received SIGNAL: %v\n", sig)
// timeout을 위한 context 생성
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
logger.Println("Close Server...")
// context에 지정한 timeout만큼 shutdown 지연
if err := server.Shutdown(ctx); err != nil {
logger.Printf("error: %v\n", err)
}
}
type HTTPHandler struct{}
func (h *HTTPHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
logger.Println("Receive Request...")
time.Sleep(5 * time.Second)
res.WriteHeader(http.StatusOK)
res.Write([]byte("OK\n"))
logger.Println("Send Response...")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment