go: x/net/http2: retry requests rejected with REFUSED_STREAM
What version of Go are you using (go version)?
go1.8.1.typealias
What operating system and processor architecture are you using (go env)?
Linux amd64
What did you do?
go run refused-stream.go -bucket veener-jba-doc-test-bucket -object datastore
Where refused-stream.go is https://gist.github.com/jba/9e75c3aedeb4e8b98a323424283fae88.
(veener-jba-doc-test-bucket/datastore should be publicly readable, but I’m guessing any object would do.)
What did you expect to see?
No output.
What did you see instead?
Often (not always), it fails with
2017/07/11 16:09:29 url Error &url.Error{Op:"Get", URL:"https://storage.googleapis.com/veener-jba-doc-test-bucket/datastore", Err:http.http2StreamError{StreamID:0xdd, Code:0x7, Cause:error(nil)}}, temporary=false, timeout=false
2017/07/11 16:09:29 NewReader: Get https://storage.googleapis.com/veener-jba-doc-test-bucket/datastore: stream error: stream ID 221; REFUSED_STREAM (*url.Error)
exit status 1
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 17 (12 by maintainers)
Commits related to this issue
- http2: retry requests after receiving REFUSED STREAM RoundTrip will retry a request if it receives REFUSED_STREAM. To guard against servers that use REFUSED_STREAM to encourage rate limiting, or serv... — committed to golang/net by tombergan 7 years ago
- http2: block RoundTrip when the Transport hits MaxConcurrentStreams Currently if the http2.Transport hits SettingsMaxConcurrentStreams for a server, it just makes a new TCP connection and creates the... — committed to golang/net by tombergan 7 years ago
- http2: retry requests after receiving REFUSED STREAM RoundTrip will retry a request if it receives REFUSED_STREAM. To guard against servers that use REFUSED_STREAM to encourage rate limiting, or serv... — committed to c3mb0/net by tombergan 7 years ago
- http2: block RoundTrip when the Transport hits MaxConcurrentStreams Currently if the http2.Transport hits SettingsMaxConcurrentStreams for a server, it just makes a new TCP connection and creates the... — committed to c3mb0/net by tombergan 7 years ago
This isn’t a GFE bug implementing HTTP/2 wrong.
This is GCS (via the GFE) telling us to slow down it seems. But I can’t reproduce. Maybe their rate limiting likes me more.
Oh, if I crank it up 10x I can get the error. With
GODEBUG=http2debug=2:It’s not clear what the GFE wants us to do, though: if it didn’t want us to open 100 concurrent streams, why did it tell us to?
So, okay, maybe it doesn’t like something else, like the rate (which isn’t expressible as a SETTING), so it sends us a REFUSED_STREAM instead.
What are we supposed to do? Retry in a loop forever? With some exponential backoff I guess?
Yeah, http://httpwg.org/specs/rfc7540.html#Reliability says:
So, yeah, do that.
/cc @tombergan