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
.
我是 运行 Go 的小客户。我们目前收到了一些误报,这似乎归结为 client.Do()
在 num>=1000
.
这是我的代码的本质:
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
.