Golang HTTP 并发请求数 POST EOF

Golang HTTP Concurrent Requests POST EOF

我是 运行 Go 的小客户。我们目前收到了一些误报,这似乎归结为 client.Do()num>=1000.

时返回 EOF 错误

这是我的代码的本质:

func DoCreate(js string, cli *http.Client) {

    url2 := "http://xvz.myserver.com:9000/path/create"

    postBytesReader := bytes.NewReader([]byte(js))
    request, _ := http.NewRequest("POST", url2, postBytesReader)

    resp, err := cli.Do(request)
    if err != nil {
        fmt.Println(err) // Post http://xvz.myserver.com:9000/path/create: EOF 
        return
    }
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))

    defer resp.Body.Close()
}

func main() {
    client := &http.Client{
        CheckRedirect: nil,
    }

    for i := 0; i < num; i++ {
        var pq CreateReqInfo
        pq.Uid = strconv.Itoa(bid + i)
        petstr, _ := json.Marshal(pq)
        go DoCreate(string(petstr), client)
    }
}

文件句柄数或最大连接数有问题吗?

  • 首先,每次 client := &http.Client{...DoCreate() 循环中实例化新客户端有什么用?客户端可以 甚至可以同时重用,所以你可以更全局地构建它, 在我看来 main() 中的说法。
  • 然后对我来说这样的错误看起来像 由 RoundTrip 生成,因此通过连接生成,因此可能来自服务器站点。你是否可以 用模拟服务器测试?
  • 最后,如果所有这些都无济于事,那么 是的,有些系统对打开的数量有限制 每个 net.Conn 都想拥有的 FileDescriptors。这个 只能在 OS 级别取消限制。

EOF 通常来自未返回完整 header(包括两个 CRLF)的服务器,或者连接在 header 完成之前关闭。您的服务器更有可能因并发请求而超载,但您仍应确保本地有足够的资源来满足您发出的并发请求的数量。如果 num 足够大,你会 运行 出一些东西。

虽然该错误并不是真正的描述性错误,但与任何其他请求错误相比,它没有什么值得担心的。这是一个错误情况,请像处理其他情况一样处理它。如果您想确定地知道,您可能必须对导致 EOF.

的连接进行数据包捕获

在我看来,您可能遇到了 this answer 中描述的问题。基本上,Go http 客户端将尝试重用连接,除非您明确指出它不应该在 Transport 中设置您的 Client 实例或在请求本身上使用:

request.Close = true

当另一端的服务器没有在响应中用 Connection: close header 指示关闭连接时,这就会成为一个问题。 net.http 代码假定连接仍处于打开状态,因此下一个尝试使用该连接的请求会遇到另一次关闭连接的 EOF

您需要检查第 1000 个请求前后连接上发生了什么。接收服务器是否设置为限制每个客户端的连接数?您的代码是否 运行ning 连接超时?在任何一种情况下,如果服务器以 Go Client 代码无法预测的方式关闭连接,那么您将 运行 进入 EOF.