Skip to content
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

HTTP2: REFUSED_STREAM not placed in graceful drain state? #13405

Closed
JamesNK opened this issue Aug 24, 2019 · 5 comments
Closed

HTTP2: REFUSED_STREAM not placed in graceful drain state? #13405

JamesNK opened this issue Aug 24, 2019 · 5 comments
Assignees
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions bug This issue describes a behavior which is not expected - a bug. feature-kestrel ✔️ Resolution: Duplicate Resolved as a duplicate of another issue HTTP2

Comments

@JamesNK
Copy link
Member

JamesNK commented Aug 24, 2019

Issue found during HTTP2 stress testing. One HttpClient is sending multiple requests in parallel, then canceling them via RST_STREAM sent to the server. For an unknown reason (#13406) the server and client disagree on the active stream count, and the sever eventually sends RST_STREAM (REFUSED_STREAM) and GOAWAY (STREAM_CLOSED).

Stream closed with REFUSED_STREAM should go into a graceful drain state and additional content sent to it from the client is ignored.

@Tratcher:

Look back in the trace to frame 281508. A bunch of server frames were bundled together, including a RST_STREAM (REFUSED_STREAM) and GOAWAY (STREAM_CLOSED).

It looks like stream 206249 was a POST immediately followed by data. That stream gets refused for some reason we’ll need to investigate, there should be something in the server logs.

Because the stream was refused, it was never added to the stream collection and placed into a graceful drain state. When the data frame is parsed it’s treated as a protocol error (frame sent to a closed stream) and the server initiates a GOAWAY.

Wireshark log: https://www.dropbox.com/s/5ndspth4t0qjyj6/clientreset-error.zip?dl=0

Exception on the client:

Unhandled exception. System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The request was aborted.
---> System.IO.IOException: The response ended prematurely, with at least 9 additional bytes expected.
   at System.Net.Http.Http2Connection.ReadAtLeastAsync(Stream stream, Memory`1 buffer, Int32 minReadBytes)
   at System.Net.Http.Http2Connection.EnsureIncomingBytesAsync(Int32 minReadBytes)
   at System.Net.Http.Http2Connection.ReadFrameAsync(Boolean initialFrame)
   at System.Net.Http.Http2Connection.ProcessIncomingFramesAsync()
   --- End of inner exception stack trace ---
   at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
   at System.Net.Http.Http2Connection.Http2Stream.TryEnsureHeaders()
   at System.Net.Http.Http2Connection.Http2Stream.ReadResponseHeadersAsync(CancellationToken cancellationToken)
   at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.Http2Connection.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Grpc.Net.Client.Internal.GrpcCall`2.SendAsync(HttpClient client, HttpRequestMessage message)
   at Grpc.Net.Client.Internal.GrpcCall`2.GetResponseHeadersAsync()

Repo is currently not public. Contact @JamesNK or @Tratcher for the repo source code and instruction.

@Tratcher Tratcher added area-servers bug This issue describes a behavior which is not expected - a bug. HTTP2 feature-kestrel labels Aug 24, 2019
@Tratcher
Copy link
Member

Tratcher commented Aug 24, 2019

Note this issue is secondary to figuring out why the stream was refused in the first place (#13406). It seems the client and server still disagree on the number of active streams. The scenario for this repro involved frequent cancellations/RSTs by the client for POST requests.

@JamesNK
Copy link
Member Author

JamesNK commented Aug 26, 2019

This is a bug but not a critical one. 3.1 fix?

@halter73 halter73 self-assigned this Aug 27, 2019
@halter73 halter73 added this to the 3.1.0 milestone Aug 27, 2019
@analogrelay
Copy link
Contributor

We can see about this for 3.1 but the bar is pretty high. I'd expect this to bump.

@Tratcher
Copy link
Member

#17484 looks like another scenario that can trigger this: Start a connection and then flood it with streams before you get the first Settings that tell you the actual stream limit. The streams are refused OK, but any subsequent data frames cause the connection to fault.
Http2ConnectionErrorException: HTTP/2 connection error (STREAM_CLOSED): The client sent a DATA frame to closed stream ID 9.

@analogrelay analogrelay added the ✔️ Resolution: Duplicate Resolved as a duplicate of another issue label Dec 2, 2019
@analogrelay
Copy link
Contributor

Going to dupe this to the other issue since the other issue has a concrete scenario ;).

@analogrelay analogrelay removed this from the 5.0.0-preview1 milestone Dec 2, 2019
@ghost ghost locked as resolved and limited conversation to collaborators Jan 2, 2020
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Jun 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions bug This issue describes a behavior which is not expected - a bug. feature-kestrel ✔️ Resolution: Duplicate Resolved as a duplicate of another issue HTTP2
Projects
None yet
Development

No branches or pull requests

5 participants