Утечка памяти на веб-сервере Golang в crypto / tls. (* Block) .reserve - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть веб-сервер, написанный на Go.

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.

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

Я провел последние дни, читая каждую статью, документ, сообщение в блоге, исходный код, файл справки, которые я мог найти. Однако ничего не помогает. Код выполняется на компьютере с Ubuntu 17.10 x64 с использованием Go 1.11 внутри контейнера Docker.

Похоже, сервер не закрывает соединения с клиентом. Я думал, что установка всех xyzTimeout поможет, но это не помогло.

Есть идеи?

Изменить 20/12/2018:

исправлено https://github.com/golang/go/issues/28654#issuecomment-448477056

1 Ответ

0 голосов
/ 01 февраля 2019

Добавление ответа, чтобы он не появлялся в списке вопросов с ответами и без ответа.

Похоже, что утечка памяти была связана с ошибкой контекста горилл https://github.com/gorilla/sessions/commit/12bd4761fc66ac946e16fcc2a32b1e0b066f6177 и не имела никакого отношения к tls в stdlib.

...