Утечка горутины в aws-sdk-go?

У меня есть следующий фрагмент кода, использующий текущий выпуск aws-sdk-go v1.7.9.

sess, _ := session.NewSession()
s3client := s3.New(sess)
location, err := s3client.GetBucketLocation(&s3.GetBucketLocationInput{Bucket: &bucket})

Я регистрирую стек вызовов до и после вызова GetBucketLocation (). Я вижу, что общее количество горутин увеличилось на два, после чего были запущены эти две дополнительные горутины:

goroutine 45 [IO wait]:
net.runtime_pollWait(0x2029008, 0x72, 0x8)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/runtime/netpoll.go:160 +0x59
net.(*pollDesc).wait(0xc420262610, 0x72, 0xc42003e6f0, 0xc4200121b0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/fd_poll_runtime.go:73 +0x38
net.(*pollDesc).waitRead(0xc420262610, 0xbcb200, 0xc4200121b0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/fd_poll_runtime.go:78 +0x34
net.(*netFD).Read(0xc4202625b0, 0xc42022fc00, 0x400, 0x400, 0x0, 0xbcb200, 0xc4200121b0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/fd_unix.go:243 +0x1a1
net.(*conn).Read(0xc42023c068, 0xc42022fc00, 0x400, 0x400, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/net.go:173 +0x70
crypto/tls.(*block).readFromUntil(0xc42017c060, 0x2029248, 0xc42023c068, 0x5, 0xc42023c068, 0xc400000000)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/crypto/tls/conn.go:476 +0x91
crypto/tls.(*Conn).readRecord(0xc42029a000, 0x840917, 0xc42029a108, 0xc420116ea0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/crypto/tls/conn.go:578 +0xc4
crypto/tls.(*Conn).Read(0xc42029a000, 0xc420196000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/crypto/tls/conn.go:1113 +0x116
net/http.(*persistConn).Read(0xc42000ba00, 0xc420196000, 0x1000, 0x1000, 0x23d3b0, 0xc42003eb58, 0x7a8d)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/http/transport.go:1261 +0x154
bufio.(*Reader).fill(0xc42000cba0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/bufio/bufio.go:97 +0x10c
bufio.(*Reader).Peek(0xc42000cba0, 0x1, 0xc42003ebbd, 0x1, 0x0, 0xc42000cc00, 0x0)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/bufio/bufio.go:129 +0x62
net/http.(*persistConn).readLoop(0xc42000ba00)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/http/transport.go:1418 +0x1a1
created by net/http.(*Transport).dialConn
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/http/transport.go:1062 +0x4e9

goroutine 46 [select]:
net/http.(*persistConn).writeLoop(0xc42000ba00)
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/http/transport.go:1646 +0x3bd
created by net/http.(*Transport).dialConn
        /usr/local/Cellar/go/1.7.4_2/libexec/src/net/http/transport.go:1063 +0x50e

Эти процедуры не исчезают со временем, и они продолжают накапливаться по мере того, как делается больше вызовов GetBucketLocation ().

Я что-то делаю не так (не закрываю какой-то ресурс) или в aws-sdk-go происходит утечка горутин?

Обратите внимание, такое же поведение наблюдается с функцией s3manager.Downloader::Download().


person jessesuen    schedule 15.03.2017    source источник
comment
Активные подключения являются нормальным явлением для HTTP-клиента, и у вас может быть несколько подключений к каждому удаленному хосту, с которым вы связались. Они растут без ограничений?   -  person JimB    schedule 15.03.2017


Ответы (1)


Оказывается, я был неправ, говоря, что рутины не исчезают со временем. Если я добавлю 10-секундный сон после вызова GetBucketLocation перед распечаткой стека горутин, то лишние процедуры действительно исчезнут.

Я считаю, что причина этого в том, что пакет net / http golang поддерживает какой-то пул соединений, который можно использовать повторно. См. Следующее обсуждение: https://groups.google.com/forum/#!topic/golang-nuts/QckzdZmzlk0

Достаточно долгое ожидание, кажется, в конечном итоге закрывает соединения и останавливает горутины.

person jessesuen    schedule 15.03.2017