Go語言HTTP服務生命週期

在 go 語言裏啓動一個 http 服務很是簡單,只須要一行代碼http.ListenAndServe()就能夠搞定,這個方法會一直阻塞着直到進程關閉,若是這個時候來了些特殊的需求好比:前端

  • 監聽服務啓動
  • 手動關閉服務
  • 監聽服務關閉

在 go 中應該怎麼實現呢?下面來一一舉例。docker

監聽服務啓動

方法一(推薦)

Listen步驟拆分出來,先監聽端口,再綁定到server上,代碼示例:tcp

l, _ := net.Listen("tcp", ":8080")
// 服務啓動成功,進行初始化
doInit()
// 綁定到server上
http.Serve(l, nil)

方法二

經過一個協程去輪詢監聽服務啓動狀態,代碼示例:spa

go func() {
    for {
        if _, err := net.Dial("tcp", "127.0.0.1:8080"); err == nil {
            // 服務啓動成功,進行初始化
            doInit()
            //退出協程
            break
        }
        // 每隔一秒檢查一次服務是否啓動成功
        time.Sleep(time.Second)
    }
}()
http.ListenAndServe(":8080", nil)

手動關閉服務

優雅關閉(推薦)

http包中並無暴露服務的關閉方法,經過http.ListenAndServe()方法啓動的 http 服務默認幫咱們建立了一個*http.Server對象,源碼以下:code

func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
}

實際上在*http.Server中是有提供Shutdown方法的,因此咱們只須要手動構造一個*http.Server對象,就能夠進行優雅關閉了,代碼示例:server

srv := &http.Server{Addr: ":8080"}
go func(){
    // 10秒以後關閉服務
    time.Sleep(time.Second * 10)
    srv.Shutdown(context.TODO())
}()
// 啓動服務
srv.ListenAndServe()

強制關閉

強制關閉和上面步驟是同樣的,只是調用的方法換成了srv.Close(),這會致使全部的請求當即中斷,因此須要特別注意。協程

監聽服務關閉

當咱們手動將服務關閉以後,srv.ListenAndServe()方法就會當即返回,這裏須要注意的是該方法會返回一個error,固然這個error是一個特殊的 error http.ErrServerClosed,幫助咱們區分是否爲正常的服務關閉,因此須要對它特殊處理下,代碼示例:對象

if err := server.ListenAndServe(); err != nil {
    // 服務關閉,進行處理
    doShutdown()
    if err != http.ErrServerClosed{
        // 異常宕機,打印錯誤信息
        log.Fatal(err)
    }
}

參考資料

我是 MonkeyWie,歡迎掃碼👇👇關注!不按期在公衆號中分享 JAVAGolang前端dockerk8s等乾貨知識。

wechat

相關文章
相關標籤/搜索