Служба Go HTTP, реализованная с помощью Gin, отправляет около 50% данных, а затем закрывает соединение, почему? - PullRequest
0 голосов
/ 09 октября 2019

У меня есть служба HTTP, которая отправляет очень большие файлы клиенту (чаще всего от 50 МБ до 100 МБ). Когда я запускаю несколько клиентов параллельно, я часто получаю часть файла (от 500 КБ до 25 МБ), а затем сервер закрывает соединение.

Если я единственный, кто делает GET с однимСоединение, оно не закрывает соединение, пока не будет передан весь файл. Так что сервис работает, когда он не загружен.

Вот как выглядит мой обработчик Gin:

func handler(c *gin.Context) {
    ...some initialization...

    // prepare list of readers
    readers := []io.Reader{}
    size := 0

    ...load some data in a []byte buffer...

    // create one reader and stack it in `readers`
    readers = append(readers, bytes.NewReader(data))
    size += len(data)

    ...repeat as needed for this request...

    // create stream
    r := io.MultiReader(readers...)

    // send data
    c.Status(http.StatusOK)  // HTTP 200 response
    c.Header("Content-Length", strconv.FormatInt(size, 10))
    io.CopyN(c.Writer, audioReader, size)
}

Как я уже говорил, процесс работает просто отлично, когда я выполняю один GET ввремя и ожидание завершения.

Когда я запускаю два или более GET параллельно, вот когда все обрывается.

Мне интересно, будет ли повторно использоваться соединение Gin TCP и, таким образом,io.CopyN() прервется до его завершения. Если да, то как мне ждать, чтобы убедиться, что io.CopyN() сделано?!

Я знаю, что close() возможен, если я непосредственно контролирую сокет, но это не работает, еслиHTTP-протокол гласил keep-alive, но, в конце концов, возможно, я иду по пятам Джин. У меня есть несколько интеграционных тестов, которые отправляют / получают сотни соединений и передает Мб данных, и они прекрасно работают. Только я никогда не посылаю два запроса параллельно в этих тестах (по крайней мере, пока).

...