-
Notifications
You must be signed in to change notification settings - Fork 18k
net/http: HTTP/2 with MaxConnsPerHost hangs or crashes #34941
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
Comments
/cc @bradfitz |
As written, the test case as a data race.
The failure does still occur but I can get a few successful runs. It is the same for 1.13.3 and tip (46aa835)
|
A fix is coming shortly. We cannot blindly decrement the conn count. We need to only decrement if we have removed the idle connection. |
Bah. A simple tweak to our existing test for MaxConnsPerHost has uncovered yet another issue.
|
All I have determined at this point is that the http2 side starts sending back |
Change https://golang.org/cl/202087 mentions this issue: |
Part of the issue is the connection coordination between http and http2. When using 300 clients, the first 50+ compete to create the connection on the http side before the http2 side is aware of it. There is some glitch (still investigating) when the http2 side is aware, it actually causes a second connection. |
The http2 server imposes a limit of 250 concurrent streams. Once we reach that number which does happen when we stampede with 300 requests, there is a point where a new connection is created. |
There is still a certain chance to crash with "internal error: connCount underflow" on golang 1.13.4 when go client enables HTTP2. |
Can you also provide the stack trace? And the potential scenario if different than reported. |
This test still fails on golang 1.13.4.
|
The fix only went into 1.14. |
Why isn't this backported? Maybe we need to ping someone? It's clearly a bug and regression in 1.13. 1.14 should be released fairly soon but that's a major release with tons of changes (the runtime in particular) that may come with its own bag of problems. |
@gopherbot please backport to 1.13 This is a regression, as documented in the issue comments. |
Backport issue(s) opened: #36583 (for 1.13). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases. |
I fear that this issue is not resolved completely: In Go version panic: net/http: internal error: connCount underflow goroutine 247 [running]: net/http.(*Transport).decConnsPerHost(0xc0000963c0, 0x0, 0x0, 0xc00038caf0, 0x5, 0xc0000f9660, 0x11, 0x0) /usr/local/go/src/net/http/transport.go:1334 +0x604 net/http.(*Transport).roundTrip(0xc0000963c0, 0xc000312e00, 0xc000374600, 0xc0001e040c, 0xc0001e0450) /usr/local/go/src/net/http/transport.go:546 +0x77f net/http.(*Transport).RoundTrip(0xc0000963c0, 0xc000312e00, 0xc0000963c0, 0xbf8140581cdfd498, 0xe2c22493c) /usr/local/go/src/net/http/roundtrip.go:17 +0x35 net/http.send(0xc000312c00, 0x1356060, 0xc0000963c0, 0xbf8140581cdfd498, 0xe2c22493c, 0x15254e0, 0xc0000fc1f8, 0xbf8140581cdfd498, 0x1, 0x0) /usr/local/go/src/net/http/client.go:250 +0x443 net/http.(*Client).send(0xc000082c00, 0xc000312c00, 0xbf8140581cdfd498, 0xe2c22493c, 0x15254e0, 0xc0000fc1f8, 0x0, 0x1, 0x0) /usr/local/go/src/net/http/client.go:174 +0xfa net/http.(*Client).do(0xc000082c00, 0xc000312c00, 0x0, 0x0, 0x0) /usr/local/go/src/net/http/client.go:641 +0x3ce net/http.(*Client).Do(...) /usr/local/go/src/net/http/client.go:509 main.main.func2.1(0xc000082c00, 0xc0001c94c0, 0xc000312c00) /Users/michaeldorner/Code/Go/src/main.go:80 +0x4d created by main.main.func2 /Users/michaeldorner/Code/Go/src/main.go:79 +0x8c exit status 2 Lines 1332 and 1333 in https://golang.org/src/net/http/transport.go explain that this Please let me know if I shall create a new issue. |
@michaeldorner This has not be backported to 1.13 yet. |
@fraenkel Oh sorry, my bad. Thanks for the fast reply. |
I'm still getting |
@andybalholm can you attach the stack trace? |
Here is the stack trace:
The usage is in a forward proxy server (github.com/andybalholm/redwood). We have about 2000 users running through the server I have been watching these errors on the most closely. So the usage is heavy, and probably about as close to random as you are likely to find. I thought that switching to two Transports (one for HTTP/1.1 and one for HTTP/2) instead of one I had |
@andybalholm Thanks for the stacktrace. Please open a separate issue to track this. It is a different path than the one fixed. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes: The test hangs with Go 1.13. The test panics with tip.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Using an
http.Client
with anhttp.Transport
configured to use http/2 and withMaxConnsPerHost = 1
, I started a large number of concurrent http/2 requests: more than the server would allow on a single TCP connection.In the test environment, I did this by having the server delay its responses until I knew a large number of requests were either active on the connection or waiting for permission to use the connection, at which point I allowed the
http.Handler
to respond.What did you expect to see?
I expected that every request I started would eventually be seen by the server, and that the client would receive the server's response.
What did you see instead?
In Go 1.11 where the default behavior is to use a single TCP connection for each http/2 authority, the requests queue up and once I allow the handler to return they are all processed. That's fine in this context.
In Go 1.12 where the http.Transport is correctly able to use more than one TCP connection for each http/2 authority (but doesn't yet know how to use
MaxConnsPerHost
), it passes all of the requests on to the server immediately. That's also fine in this context.In Go 1.13, the server only sees the first 249 requests. The others appear stuck indefinitely. I see that as a bug.
In tip, the Transport panics. That's a second bug.
And for context, the passing results with Go 1.11 and Go 1.12:
The text was updated successfully, but these errors were encountered: