首页 > 解决方案 > golang服务器中的连接卡在CLOSE_WAIT

问题描述

我正在使用 gorilla mux 创建一个 golang 服务器来支持一个简单的健康 GET 端点。只要服务器启动,端点就会以 ok 状态响应。我在一个系统上看到很多处于 CLOSE_WAIT 状态的连接(超过 400 个)。这不会发生在具有相同代码的其他系统上。netstat 的输出(9003 是我的服务器端口):

tcp      164      0 ::1:9003                    ::1:60702                   CLOSE_WAIT  -
tcp      164      0 ::1:9003                    ::1:44472                   CLOSE_WAIT  -
tcp      164      0 ::1:9003                    ::1:31504                   CLOSE_WAIT  -

这似乎意味着我有一个需要关闭的连接。我在网上阅读的大多数问题似乎都表明打开的连接与客户端在 GET 后没有发出 response.body.close() 有关。根据https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/,我可以在服务器端添加读/写超时,但我想了解 CLOSE_WAITS 的根本原因在添加改进之前。

我错过了服务器端的任何关闭吗?

我的代码如下:

import  "github.com/gorilla/mux"
...

func (server *Srvr) healthHandler(w http.ResponseWriter, r *http.Request) {
    resp := map[string]string{"status": "ok"}
    respJSON, err := json.Marshal(resp)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        fmt.Fprintf(w, "Error creating JSON response %s", err)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write(respJSON)
}


// Load initializes the servers
func Load(port string) *Srvr {
    srvrPort := ":" + port
    log.Infof("Will listen on port %s", srvrPort)
    serverMux := mux.NewRouter()
    srvr := &Srvr{Port: port, Srv: &http.Server{Addr: srvrPort, Handler: serverMux}}
    serverMux.HandleFunc("/api/v1.0/health", srvr.healthHandler).Methods("GET")
    return srvr
}

// Run starts the server
func (server *Srvr) Run() {
    log.Info("Starting the server")

    // Starting a server this way to allow for shutdown.
    // https://stackoverflow.com/questions/39320025/how-to-stop-http-listenandserve
    err := server.Srv.ListenAndServe()
    if err != http.ErrServerClosed {
        log.Fatalf("ListenAndServe(): %s", err)
    }
}
// Main resides outside the server package
func main() {

    srvr := server.Load("9003")
    // Now that all setup is done successfully, lets start the server
    go srvr.Run()
    // An unrelated forever loop executes below for different business logic
for {
        glog.Info("Evaluation iteration begins now")
        ...

        time.Sleep(time.Duration(evalFreq) * time.Minute)
    }

}

标签: goserver

解决方案


推荐阅读