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

[8.0] HTTP/2 request to cloud hosted services is aborted by server with ENHANCE_YOUR_CALM #97131

Open
JamesNK opened this issue Jan 18, 2024 · 2 comments · Fixed by #97881
Open
Assignees
Labels
area-System.Net.Http in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@JamesNK
Copy link
Member

JamesNK commented Jan 18, 2024

Description

Two gRPC users have reported problems with streaming calls make to services hosted by GCP/Google:

The streaming calls end after a small amount of activity with this error:

System.Net.Http.HttpIOException: The response ended prematurely while waiting for the next frame from the server. (ResponseEnded)
   at System.Net.Http.Http2Connection.ThrowRequestAborted(Exception innerException)
   at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
   at System.Net.Http.Http2Connection.Http2Stream.TryReadFromBuffer(Span`1 buffer, Boolean partOfSyncRead)
   at System.Net.Http.Http2Connection.Http2Stream.ReadDataAsync(Memory`1 buffer, HttpResponseMessage responseMessage, CancellationToken cancellationToken)

They're both verified that only the .NET client has this problem. Other gRPC implementations (Rust, go, Python) are successful.

Debugging logs shows that the problem is caused by the server aborting the connection because the client is sending too many pings. Logs:

poolId=44799463 workerId=57352375 requestId=0 memberName=ProcessOutgoingFramesAsync message=writeBytes=17
poolId=44799463 workerId=57352375 requestId=0 memberName=SendPingAsync message=Started writing. pingContent=-5
poolId=44799463 workerId=57352375 requestId=0 memberName=FlushOutgoingBytesAsync message=ActiveLength=17
poolId=44799463 workerId=57352375 requestId=0 memberName=ReadFrameAsync message=initialFrame=False
poolId=44799463 workerId=57352375 requestId=0 memberName=ProcessIncomingFramesAsync message=Frame 13: StreamId=0; Type=GoAway; Flags=None; PayloadLength=22.
poolId=44799463 workerId=57352375 requestId=0 memberName=ReadGoAwayFrame message=lastStreamId=1, errorCode=EnhanceYourCalm

The client sends a ping to the server, and the server responds with a GOAWAY with an error code of ENHANCE_YOUR_CALM.

The problem can be worked around by disabling RTT pings:

AppContext.SetSwitch("System.Net.SocketsHttpHandler.Http2FlowControl.DisableDynamicWindowSizing", true);

Reproduction Steps

A customer has created a reproduction - grpc/grpc-dotnet#2361

Expected behavior

HttpClient should be able to successfully call GCP/Google hosted endpoints without the server aborting the connection.

Resolving this problem requires low level knowledge of HTTP/2 and client/server interactions. There is no way developers will understand how to solve this problem.

Actual behavior

GOAWAY + ENHANCE_YOUR_CALM

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

@ghost
Copy link

ghost commented Jan 18, 2024

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

Two gRPC users have reported problems with streaming calls make to services hosted by GCP/Google:

The streaming calls end after a small amount of activity with this error:

System.Net.Http.HttpIOException: The response ended prematurely while waiting for the next frame from the server. (ResponseEnded)
   at System.Net.Http.Http2Connection.ThrowRequestAborted(Exception innerException)
   at System.Net.Http.Http2Connection.Http2Stream.CheckResponseBodyState()
   at System.Net.Http.Http2Connection.Http2Stream.TryReadFromBuffer(Span`1 buffer, Boolean partOfSyncRead)
   at System.Net.Http.Http2Connection.Http2Stream.ReadDataAsync(Memory`1 buffer, HttpResponseMessage responseMessage, CancellationToken cancellationToken)

They're both verified that only the .NET client has this problem. Other gRPC implementations (Rust, go, Python) are successful.

Debugging logs shows that the problem is caused by the server aborting the connection because the client is sending too many pings. Logs:

poolId=44799463 workerId=57352375 requestId=0 memberName=ProcessOutgoingFramesAsync message=writeBytes=17
poolId=44799463 workerId=57352375 requestId=0 memberName=SendPingAsync message=Started writing. pingContent=-5
poolId=44799463 workerId=57352375 requestId=0 memberName=FlushOutgoingBytesAsync message=ActiveLength=17
poolId=44799463 workerId=57352375 requestId=0 memberName=ReadFrameAsync message=initialFrame=False
poolId=44799463 workerId=57352375 requestId=0 memberName=ProcessIncomingFramesAsync message=Frame 13: StreamId=0; Type=GoAway; Flags=None; PayloadLength=22.
poolId=44799463 workerId=57352375 requestId=0 memberName=ReadGoAwayFrame message=lastStreamId=1, errorCode=EnhanceYourCalm

The client sends a ping to the server, and the server responds with a GOAWAY with an error code of ENHANCE_YOUR_CALM.

The problem can be worked around by disabling RTT pings:

AppContext.SetSwitch("System.Net.SocketsHttpHandler.Http2FlowControl.DisableDynamicWindowSizing", true);

Reproduction Steps

A customer has created a reproduction - grpc/grpc-dotnet#2361

Expected behavior

HttpClient should be able to successfully call GCP/Google hosted endpoints without the server aborting the connection.

Resolving this problem requires low level knowledge of HTTP/2 and client/server interactions. There is no way developers will understand how to solve this problem.

Actual behavior

GOAWAY + ENHANCE_YOUR_CALM

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Author: JamesNK
Assignees: -
Labels:

area-System.Net.Http

Milestone: -

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jan 18, 2024
@antonfirsov antonfirsov removed the untriaged New issue has not been triaged by the area owner label Jan 18, 2024
@antonfirsov antonfirsov added this to the 9.0.0 milestone Jan 18, 2024
@antonfirsov antonfirsov self-assigned this Jan 18, 2024
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Feb 2, 2024
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 13, 2024
@antonfirsov antonfirsov modified the milestones: 9.0.0, 6.0.x Feb 13, 2024
@antonfirsov antonfirsov reopened this Feb 13, 2024
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Feb 27, 2024
@antonfirsov
Copy link
Member

Backport will happen after 9.0 GA, moving to Future.

@antonfirsov antonfirsov modified the milestones: 9.0.0, Future Jun 5, 2024
@karelz karelz modified the milestones: Future, 8.0.x Jun 11, 2024
@karelz karelz changed the title HTTP/2 request to cloud hosted services is aborted by server with ENHANCE_YOUR_CALM [8.0] HTTP/2 request to cloud hosted services is aborted by server with ENHANCE_YOUR_CALM Jun 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Net.Http in-pr There is an active PR which will close this issue when it is merged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants