【问题标题】:why is golang http server failing with "broken pipe" when response exceeds 8kb?当响应超过 8kb 时,为什么 golang http 服务器会因“管道损坏”而失败?
【发布时间】:2017-08-28 14:23:40
【问题描述】:

我在下面有一个示例网络服务器,如果您立即调用curl localhost:3000 -v 然后^C(取消)它(1 秒前),它将报告write tcp 127.0.0.1:3000->127.0.0.1:XXXXX: write: broken pipe

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    log.Fatal(http.ListenAndServe(":3000", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            time.Sleep(1 * time.Second)

            // Why 8061 bytes? Because the response header on my computer
            // is 132 bytes, adding up the entire response to 8193 (1 byte 
            // over 8kb)
            if _, err := w.Write(make([]byte, 8061)); err != nil {
                    fmt.Println(err)
                    return
            }   
    })))
}

根据我的调试,我已经能够得出结论,只有当整个响应写入超过 8192 字节(或 8kb)时才会发生这种情况。如果我的整个响应写入少于 8192,则不会返回 broken pipe 错误。

我的问题是这个 8192 字节(或 8kb)的缓冲区限制在哪里设置?这是 Golang 的 HTTP 写入缓冲区的限制吗?这与响应被分块有关吗?这仅与curl 客户端或浏览器客户端有关吗?如何更改此限制,以便在连接关闭之前写入更大的缓冲区(出于调试目的)?

谢谢!

【问题讨论】:

    标签: http curl go httpresponse


    【解决方案1】:

    net/http/server.go 中,输出缓冲区设置为4<<10,即4KB。

    您在 8KB 处看到错误的原因是,它需要至少 2 次写入套接字才能检测到已关闭的远程连接。第一次写入成功,但是远程主机发送了一个RST包。第二次写入将是一个关闭的套接字,这就是返回 broken pipe 错误的原因。

    根据套接字写入缓冲区和连接延迟,在注册第一个 RST 数据包之前,可能会成功进行更多写入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-15
      • 1970-01-01
      相关资源
      最近更新 更多