代码之家  ›  专栏  ›  技术社区  ›  zemirco

Golang web服务器在crypto/tls处泄漏内存。(*block).reserve

  •  9
  • zemirco  · 技术社区  · 6 年前

    我有一个用Go写的web服务器。

    tlsConfig := &tls.Config{
        PreferServerCipherSuites: true,
        MinVersion:               tls.VersionTLS12,
        CurvePreferences: []tls.CurveID{
            tls.CurveP256,
            tls.X25519,
        },
        CipherSuites: []uint16{
            tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
            tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
            tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
            tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
            tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
        },
    }
    
    s := &http.Server{
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 10 * time.Second,
        IdleTimeout:  120 * time.Second,
        Handler:      r, // where r is my router
        TLSConfig:    tlsConfig,
    }
    
    // redirect http to https
    redirect := &http.Server{
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 10 * time.Second,
        IdleTimeout:  120 * time.Second,
        Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Connection", "close")
            url := "https://" + r.Host + r.URL.String()
            http.Redirect(w, r, url, http.StatusMovedPermanently)
        }),
    }
    go func() {
        log.Fatal(redirect.ListenAndServe())
    }()
    
    log.Fatal(s.ListenAndServeTLS(certFile, keyFile))
    

    这是我的数字海洋仪表板截图。

    enter image description here

    正如你所见,记忆一直在增长。所以我开始看 https://github.com/google/pprof . 下面是 top5 .

    Type: inuse_space
    Time: Nov 7, 2018 at 10:31am (CET)
    Entering interactive mode (type "help" for commands, "o" for options)
    (pprof) top5
    Showing nodes accounting for 289.50MB, 79.70% of 363.24MB total
    Dropped 90 nodes (cum <= 1.82MB)
    Showing top 5 nodes out of 88
          flat  flat%   sum%        cum   cum%
      238.98MB 65.79% 65.79%   238.98MB 65.79%  crypto/tls.(*block).reserve
       20.02MB  5.51% 71.30%    20.02MB  5.51%  crypto/tls.Server
       11.50MB  3.17% 74.47%    11.50MB  3.17%  crypto/aes.newCipher
       10.50MB  2.89% 77.36%    10.50MB  2.89%  crypto/aes.(*aesCipherGCM).NewGCM
    

    SVG显示了crypto/tls(*block).reserve所分配的同样大的内存量。

    enter image description here

    这是确切的代码。

    enter image description here

    我花了最后几天阅读每一篇文章,文件,博客文章,源代码,帮助文件,我可以找到。但是没有任何帮助。代码在ubuntu17.10x64机器上运行,在Docker容器中使用Go 1.11。

    服务器似乎没有关闭与客户端的连接。我想把所有的 xyzTimeout

    编辑2018年12月20日:

    https://github.com/golang/go/issues/28654#issuecomment-448477056

    1 回复  |  直到 6 年前
        1
  •  1
  •   John Weldon user3678248    5 年前

    添加一个答案,这样就不会一直出现在已投票和未回答的问题列表中。

    看来内存泄漏与gorilla上下文错误有关 https://github.com/gorilla/sessions/commit/12bd4761fc66ac946e16fcc2a32b1e0b066f6177 与标准库中的tls无关。