英文:
How to configure the buffer size for http.ResponseWriter?
问题
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.
根据我的测试,缺省的缓冲区大小是4kB。我可以看到这个应该是可以配置的,但是怎么配置呢?有人知道吗?
英文:
http.ResponseWriter
only has two functions, one is WriteHeader()
, the other is Write()
. So I figure it needs to configure in other places. Then I found this: 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.
Base on my test, the default buffer size is 4kB. I can see this is supposed to be configurable, but how? Does anyone know?
答案1
得分: 1
我看到了类似的需求,并且在过去的https://github.com/golang/go/issues/7467中建议对Server struct
进行相关更改。但是建议在需要自定义大小缓冲区的处理函数中添加自己的缓冲。
您可以按照上述github问题中的建议,通过使用自定义大小的bufio writer来配置http.ResponseWriter
的缓冲区大小。
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) // 10kb的较大写入器
fmt.Println("缓冲区大小", pw.Size())
strR := strings.Repeat("Hello from a Func1!\n", 1000) // 创建一个较大的响应
_, err := io.WriteString(pw, strR)
if err != nil {
fmt.Println(err)
}
if pw.Buffered() > 0 {
fmt.Println("已缓冲", pw.Buffered())
pw.Flush() // 重要的步骤,请阅读下面代码片段后面的注意事项
}
}
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()
。正如文档中也提到的那样。
ResponseWriters允许HTTP处理程序将缓冲数据刷新到客户端。
默认的HTTP/1.x和HTTP/2 ResponseWriter实现支持Flusher,但ResponseWriter包装器可能不支持。处理程序应始终在运行时测试此功能。
英文:
I saw the similar requirement and related change to Server struct
was suggested in the past https://github.com/golang/go/issues/7467. But it was advised to add own buffering to the handler functions which needed to have a custom sized buffer.
You can configure the buffer size for the http.ResponseWriter
by wrapping the current http.ResponseWriter
with a custom sized bufio writer as advised in the github issue above.
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))
}
Note: As we wrapped the original http.ResponseWriter
, we will need to manage buffer flushing ourself i.e. pw.Flush()
. As also mentioned in the docs.
> ResponseWriters that allow an HTTP handler to flush buffered data to
> the client.
>
> The default HTTP/1.x and HTTP/2 ResponseWriter implementations support
> Flusher, but ResponseWriter wrappers may not. Handlers should always
> test for this ability at runtime.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论