Golang 程式中實現優雅關閉 HTTP SERVER
Golang 中實現一個 HTTP SERVER 異常的簡單,利用標準庫 net/http 的實現僅需數行程式碼即可,但是一個生產環境可用的 HTTP SERVER 還必須考慮更多的問題,其中如何實現優雅關閉 HTTP SERVER 是一個必須要處理的問題。這裡所說的優雅 即是指在 HTTP SERVER 裡監聽特定的訊號,並在接收到訊號時做出相應的處理。中文世界裡也常用平滑 一詞代替,說的都是同一個意思。
如果你對 Golang 中監聽並處理訊號不瞭解,建議先花三分鐘瀏覽一下本專欄的另一篇關於訊號處理的文章:
ofollow,noindex">Golang 程式中如何監聽並處理訊號?
Talk is cheap. Show me the code.
package main import ( "context" "fmt" "net/http" "os" "os/signal" "sync" "syscall" "time" ) const addr = ":9527" func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "just another http server...") }) //使用預設路由建立 http server srv := http.Server{ Addr:addr, Handler: http.DefaultServeMux, } //使用WaitGroup同步Goroutine var wg sync.WaitGroup exit := make(chan os.Signal) //監聽 Ctrl+C 訊號 signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM) go func() { <-exit wg.Add(1) //使用context控制srv.Shutdown的超時時間 ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() err := srv.Shutdown(ctx) if err != nil { fmt.Println(err) } wg.Done() }() fmt.Println("listening at " + addr) err := srv.ListenAndServe() fmt.Println("waiting for the remaining connections to finish...") wg.Wait() if err != nil && err != http.ErrServerClosed { panic(err) } fmt.Println("gracefully shutdown the http server...") }