# #http #go #buffer
Вопрос:
http.ResponseWriter
имеет только две функции: одна есть WriteHeader()
, другая есть Write()
. Поэтому я считаю, что его нужно настроить в других местах. Затем я нашел это: https://golang.org/src/net/http/server.go L1534
// 1. *response (the ResponseWriter) ->
// 2. (*response).w, a *bufio.Writer of bufferBeforeChunkingSize bytes
// 3. chunkWriter.Writer (whose writeHeader finalizes Content-Length/Type)
// and which writes the chunk headers, if needed.
// 4. conn.buf, a bufio.Writer of default (4kB) bytes, writing to ->
// 5. checkConnErrorWriter{c}, which notes any non-nil error on Write
// and populates c.werr with it if so. but otherwise writes to:
// 6. the rwc, the net.Conn.
Основываясь на моем тесте, размер буфера по умолчанию составляет 4 КБ. Я вижу, что это должно быть настраиваемо, но как? Кто-нибудь знает?
Комментарии:
1. В чем проблема, которую вы пытаетесь решить, регулируя размер буфера?
2.
bufio.Writer
реализовано таким образом, что фрагмент байтов, больший, чем размер буфера, записывается непосредственно в базовую запись (когда буфер не пуст, будет дополнительная запись). Поэтому, как правило, нет необходимости изменять этот размер. Можете ли вы написать, какую проблему вы пытаетесь решить?3. У нас есть сервер, который генерирует аудиоданные, и он очень медленный. Скорость составляет около 4 Кб в 1,5 секунды. Таким образом, клиент начинает воспроизводить звук только через 1,5 секунды. К сожалению, я ничего не могу сделать, чтобы ускорить этот процесс. Единственное, что я могу сделать, — это оптимизировать время отклика.
4. После некоторой отладки я обнаружил, что если я смогу изменить размер буфера ответов на 2 КБ, то клиент сможет получить данные за 0,7 с и начать воспроизводить аудио.
Ответ №1:
Я видел аналогичное требование и соответствующие изменения Server struct
, которые были предложены в прошлом https://github.com/golang/go/issues/7467. Но было рекомендовано добавить собственную буферизацию к функциям обработчика, которые должны иметь буфер пользовательского размера.
Вы можете настроить размер буфера для http.ResponseWriter
, обернув текущий http.ResponseWriter
с помощью буфера записи пользовательского размера, как рекомендовано в выпуске github выше.
package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
h1 := func(w http.ResponseWriter, _ *http.Request) {
pw := bufio.NewWriterSize(w, 10<<10) // Bigger writer of 10kb
fmt.Println("Buffer size", pw.Size())
strR := strings.Repeat("Hello from a Func1!n", 1000) //just to create a bigger response
_, err := io.WriteString(pw, strR)
if err != nil {
fmt.Println(err)
}
if pw.Buffered() > 0 {
fmt.Println("Bufferred", pw.Buffered())
pw.Flush() // Important step read my note following this code snippet
}
}
h2 := func(w http.ResponseWriter, _ *http.Request) {
io.WriteString(w, "Hello from a Func2!n")
}
http.HandleFunc("/foo", h1)
http.HandleFunc("/bar", h2)
log.Fatal(http.ListenAndServe(":8080", nil))
}
Примечание: Поскольку мы завернули оригинал http.ResponseWriter
, нам нужно будет управлять сбросом буфера самостоятельно pw.Flush()
, т. е. Как также упоминалось в документах.
Пишущие строки ответов, которые позволяют обработчику HTTP сбрасывать буферизованные данные клиенту.
Реализации пишущей машинки HTTP/1.x и HTTP/2 по умолчанию поддерживают Flusher, но оболочки пишущей машинки могут этого не делать. Обработчики всегда должны проверять эту способность во время выполнения.
Комментарии:
1. Спасибо, Ник!! Это именно то, что мне нужно!
2. К сожалению, функция Flush() не очистила данные, как я ожидал. Я думаю, что он переключился на пишущую машинку ответа, но пишущая машинка по-прежнему использовала свой собственный размер буфера 4K для передачи данных клиенту…
3. Это сработало для меня, когда я попробовал точный код, написанный в ответе. Поделитесь своим фрагментом кода через игровую площадку или что-то в этом роде.
4. Я запустил ваш код и сбросил TCP-трафик. вот что я нашел: вы можете видеть, что посылка все еще 4096.
14:53:32.833985 IP6 localhost.8181 > localhost.56416: Flags [P.], seq 1:4097, ack 82, win 6370, options [nop,nop,TS val 1329849328 ecr 1588922425], length 4096 | 14:53:32.833990 IP6 localhost.8181 > localhost.56416: Flags [P.], seq 4097:8193, ack 82, win 6370, options [nop,nop,TS val 1329849328 ecr 1588922425], length 4096
5. Я думаю, что вы имеете в виду приведенную выше строку
OPTIONS
с телом чтения, которое жестко закодировано до 4 кб, см. Здесь golang.org/src/net/http/server.go#L3403 .