http server優(yōu)雅關(guān)閉的行為

友情提示:該結(jié)論當(dāng)前只在Golang http server上測(cè)試過,其他語(yǔ)言編寫的http server可以參考測(cè)試方法進(jìn)行驗(yàn)證。

測(cè)試:

  1. 使用golang寫一個(gè)支持優(yōu)雅關(guān)閉的http server,示例代碼如下:
package main

import (
    "context"
    "fmt"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"
)

// handler 處理 HTTP 請(qǐng)求
func handler(w http.ResponseWriter, r *http.Request) {
    time.Sleep(20 * time.Second)
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    // 創(chuàng)建 HTTP 服務(wù)器
    mux := http.NewServeMux()
    mux.HandleFunc("/", handler)

    server := &http.Server{
        Addr:    ":8080",
        Handler: mux,
    }

    // 創(chuàng)建一個(gè)通道來監(jiān)聽系統(tǒng)信號(hào)
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)

    // 啟動(dòng)服務(wù)器
    go func() {
        fmt.Println("Server is running on :8080")
        if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            fmt.Printf("ListenAndServe error: %v\n", err)
        }
    }()

    // 阻塞等待系統(tǒng)信號(hào)
    <-stop
    fmt.Println("Shutting down server...")

    // 創(chuàng)建超時(shí)上下文用于關(guān)閉服務(wù)器
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    if err := server.Shutdown(ctx); err != nil {
        fmt.Printf("Server forced to shutdown: %v\n", err)
    } else {
        fmt.Println("Server exited properly")
    }
}
  1. 使用http客戶端請(qǐng)求http://127.0.0.1:8080,客戶端不限,比如:curl、telnet、瀏覽器等等
  2. 使用wireshark抓包,查看服務(wù)端與客戶端之間的通信

結(jié)論:

  1. [http-client-1] 如果在http server Shutdown之前發(fā)起的請(qǐng)求,http server會(huì)繼續(xù)處理,如果在timeout時(shí)間內(nèi)處理完成則正常響應(yīng)(圖中未給出),如果timeout時(shí)間內(nèi)還未處理完成則http server強(qiáng)制使用FIN終止連接,應(yīng)用層的表現(xiàn),以curl工具為例:
$ curl -v http://127.0.0.1:8080/
*   Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080
> GET / HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
* Empty reply from server
* Closing connection
curl: (52) Empty reply from server
  1. [http-client-2] 如果客戶端在http server Shutdown過程中發(fā)起請(qǐng)求,則http server不會(huì)處理該請(qǐng)求,直接以RST包終止連接,應(yīng)用層的表現(xiàn),以curl工具為例:
$ curl -v http://127.0.0.1:8080/
*   Trying 127.0.0.1:8080...
* connect to 127.0.0.1 port 8080 from 127.0.0.1 port 61852 failed: Connection refused
* Failed to connect to 127.0.0.1 port 8080 after 0 ms: Couldn't connect to server
* Closing connection
curl: (7) Failed to connect to 127.0.0.1 port 8080 after 0 ms: Couldn't connect to server
  1. [http-client-3] 如果客戶端在http server Shutdown之前建立了連接,但是在Shutdown之前沒有發(fā)起http請(qǐng)求或者所有請(qǐng)求都已經(jīng)完成,那么http server會(huì)立即使用FIN包終止該連接。也就是說http server Shutdown時(shí),會(huì)關(guān)閉空閑連接

時(shí)序圖:更清晰的展示http server優(yōu)雅關(guān)閉的過程和行為

image.png

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容