【问题标题】:Golang web server leaking memory at crypto/tls.(*block).reserveGolang Web 服务器在 crypto/tls.(*block).reserve 泄漏内存
【发布时间】:2019-04-10 20:58:39
【问题描述】:

我有一个用 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))

这是我的 Digital Ocean 仪表板的屏幕截图。

如您所见,内存不断增长。所以我开始关注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 分配的大量内存。

这是确切的代码。

我在最后几天阅读了我能找到的每一篇文章、文档、博客文章、源代码和帮助文件。然而,没有任何帮助。该代码在 Docker 容器内使用 Go 1.11 的 Ubuntu 17.10 x64 机器上运行。

看起来服务器没有关闭与客户端的连接。我认为设置所有 xyzTimeout 会有所帮助,但没有。

有什么想法吗?

2018 年 12 月 20 日编辑:

现已修复https://github.com/golang/go/issues/28654#issuecomment-448477056

【问题讨论】:

  • Keep-Alive 默认启用。调用s.SetKeepAlivesEnabled(false) 将其禁用(但验证它是否确实适用于 HTTP 2.0)。无论如何,IdleTimeout 确实应该自动关闭空闲连接。内存消耗高时有多少活动连接?服务器是直接暴露在互联网上还是有代理?
  • «内存不断增长和增长» - 从图表中,我会说内存被分配然后被释放,在某个平均值附近振荡 - 正如我对 GC 运行时所期望的那样。或者图表上的这些下降是否意味着您的应用程序重新启动?
  • @kostix 如果您查看时间间隔,那绝不是 GC,这些或多或少是每天。可能是部署?
  • 我现在要hit the issue tracker。如果您愿意,请在此处发布问题编号。一方面,我有兴​​趣关注。
  • 我创建了一个问题github.com/golang/go/issues/28654。如果您遇到同样的问题并且可以提供更多信息,请提供。

标签: ssl go memory-leaks tls1.2


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2018-07-14
    • 2011-02-18
    相关资源
    最近更新 更多