Go socket:打开的文件太多。

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

Go socket : too many open files

问题

当我从以下代码发送请求时:

req, err := http.NewRequest("GET", "my_target:", nil)
if err != nil {
    panic(err)
}
req.Close = true
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
    panic(err)
}
defer resp.Body.Close()

在发送平均每分钟10个请求几个小时后,我收到以下错误:

socket: too many open files

我该如何找到这个问题的原因?

我没有关闭http.Request吗?

我以为req.Close = true会完成这个工作。

谢谢!

英文:

When I send requests from the following code:

req, err := http.NewRequest("GET", "my_target:", nil)
if err != nil {
    panic(err)
}
req.Close = true
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
    panic(err)
}
defer resp.Body.Close()

After a few hours of sending average 10 requests per minutes, I get this error:

socket: too many open files

How do I find the cause of this problem?

Am I not closing the http.Request?

I thought req.Close = true does that job.

Thanks!

答案1

得分: 9

为什么你要推迟关闭?你真的在读取这个body吗?

defer resp.Body.Close()

在执行另一个Get之前,你是否真的从当前函数返回?如果不是,那么defer将永远不会执行,你将永远无法释放这个连接以供重用。

在这里,req.Close = true是一个不寻常的选择。这也会阻止连接的重用,而你可能希望进行连接的重用,而不是禁止。这不会自动关闭你这边的请求。它强制服务器立即关闭连接,否则你将重用该连接。你会一直保持连接打开,直到你关闭它。

通常对于像你这里的简单GET请求,我会这样做:

resp, err := http.Get("...")
if err != nil {
    panic(err) // panic似乎有些严厉,通常你只会返回错误。但无论如何...
}
resp.Body.Close()

这里不需要一个特殊的客户端。只需使用默认的客户端即可。只要确保关闭响应体,它会处理其余的事情。如果你要立即关闭body,就不需要用defer来复杂化事情。defer的原因是确保在后续可能返回或在错误时引发恐慌时关闭body。

英文:

Why are you deferring the close? Are you actually reading from this body?

defer resp.Body.Close()

Do you actually return from the current function before performing another Get? If not, then the defer will never execute, and you'll never release this connection for reuse.

req.Close = true is an unusual choice here, as well. This also prevents connection reuse, which is something you'd probably want rather than forbid. This doesn't automatically close the request on your side. It forces the server to immediately close the connection, which you would otherwise reuse. You'll hold your side open until you close it.

Typically for a simple GET request like you have here, I would just do this:

resp, err := http.Get("...")
if err != nil {
    panic(err) // panic seems harsh, usually you'd just return the error. But either way...
}
resp.Body.Close()

There's no need for a special client here. Just use the default one. It'll take care of the rest as long as you make sure to close the response body. And there's no need to complicate things with a defer if you're going to immediately close the body. The reason for defer is to make sure you close the body if you have a bunch of processing later that might return or panic on error.

huangapple
  • 本文由 发表于 2015年7月10日 23:25:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/31344587.html
匿名

发表评论

匿名网友

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

确定