-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: http.Client not properly handling broken connections #8946
Comments
My apologies. Here's the client code: http://play.golang.org/p/UELtke0oS4 |
I think this is related to #4677, which I've made a rough attempt to fix here: https://go-review.googlesource.com/3210 |
I would sometimes see errors like: graphiteBand: graphite RequestError (http://....): Get failed: Get http://... : read tcp 10.90.128.100:80: use of closed network connection This kind of error is not something that should bubble up to the caller of a http client library, but it does. see also: golang/go#8946 golang/go#9424 there's a bunch more issues about the broken state of error handling in net/http. So anyway the http client tries to reuse an existing connection which has broken. Somehow this is the caller's problem, so we address it by not keeping any idle connection and opening a new connection each time. This should get rid of these errors without adding much overhead. Note that the used http transport is, other than the MaxIdleConnsPerHost setting, the same as the default transport.
Should retrying a TCP RST connection be limited to HEAD/GET methods when it write fails because the server closed the connection? If not would it make sense for this specific error to be returned as a net.Error instead of url.Error? Especially since it is temporary and connection related. Or would that break the 1.0 contract? Example of server read timeout for keep alive connections: https://gist.github.com/jasdel/e0346d861756e14399dc |
This appears to be fixed. With a client of: func main() {
cli := http.Client{}
for {
url := "http://localhost:8080/foo"
resp, rerr := cli.Get(url)
fmt.Printf("Get = %#v, %v\n", resp, rerr)
if rerr != nil {
continue
}
body, berr := ioutil.ReadAll(resp.Body)
fmt.Printf("ReadAll = %q, %v\n", body, berr)
resp.Body.Close()
}
} I get the same thing each time:
At first I was expecting the ioutil.ReadAll to return an UnexpectedEOF from the chunked reader, but looking at strace, it does appear the server manages to send out the EOF chunk before the connection is closed:
And if I add to the Server's Handler: println("Hello", r.RemoteAddr)
defer println("Bye", r.RemoteAddr) I see a new connection for each one:
|
by eyakubovich:
The text was updated successfully, but these errors were encountered: