如何配置http.ResponseWriter的缓冲区大小?

huangapple go评论80阅读模式
英文:

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 (
	&quot;bufio&quot;
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;strings&quot;
)

func main() {
	h1 := func(w http.ResponseWriter, _ *http.Request) {
		pw := bufio.NewWriterSize(w, 10&lt;&lt;10) // Bigger writer of 10kb
		fmt.Println(&quot;Buffer size&quot;, pw.Size())

		strR := strings.Repeat(&quot;Hello from a Func1!\n&quot;, 1000) //just to create a bigger response

		_, err := io.WriteString(pw, strR)

		if err != nil {
			fmt.Println(err)
		}

		if pw.Buffered() &gt; 0 {
			fmt.Println(&quot;Bufferred&quot;, pw.Buffered())
			pw.Flush() // Important step read my note following this code snippet
		}
	}

	h2 := func(w http.ResponseWriter, _ *http.Request) {
		io.WriteString(w, &quot;Hello from a Func2!\n&quot;)
	}

	http.HandleFunc(&quot;/foo&quot;, h1)
	http.HandleFunc(&quot;/bar&quot;, h2)

	log.Fatal(http.ListenAndServe(&quot;:8080&quot;, 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.

huangapple
  • 本文由 发表于 2021年8月14日 06:34:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/68778961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定