Golang HTTP 并发请求 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)
    }
}

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

在我看来

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

request.Close = true

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

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

  • 首先,每次client := &http.Client{...循环内部DoCreate()循环内时实例化新客户端对您来说是什么?客户端可以是甚至可以同时重用,因此您可以更全局地构建它,在我看来main()说。
  • 那么对我来说,这样的错误看起来像由RoundTrip产生,因此通过连接,因此可能来自服务器站点。你能吗使用模拟服务器进行测试?
  • 最后,如果这一切都无济于事,那么是的,某些系统对打开的数量有限制每个net.Conn都希望拥有的文件描述符。这只能在操作系统级别消除限制。

EOF通常来自未返回完整标头(包括两个CRLF)的服务器,或者在标头完成之前关闭连接。更有可能的是,您的服务器因并发请求而过载,尽管您仍应确保在本地有足够的资源来处理您发出的并发请求数。如果num足够大,你就会用完一些东西。

尽管该错误并不是真正的描述性,但与任何其他请求错误相比,没有什么值得担心的。这是一个错误条件,请像处理任何其他情况一样处理它。如果您想确定,则可能必须对导致EOF的连接进行数据包捕获。

最新更新