Add backpressure control and allow asynchronous flushing #116
+156
−25
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
I've wanted to control the amount of backpressure when reading a response using a stream. Specifically, the value of
pauseWriterThreshold
inPipeOptions.Default
of the Pipe thatCysharp.Net.Http.ResponseContext
has is 64KiB. I would like to change this value.https://github.com/dotnet/runtime/blob/b9691b06b96541e8e94cd79f17d6447b8d03ec20/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeOptions.cs#L47-L48
However, I have noticed that the progress of the other requests may be blocked when backpressure is occurring. Upon investigation, I found that this is caused by waiting for
PipeWriter.FlushAsync()
synchronously, which blocksFlushAsync()
while backpressure is occurring, blocking the worker thread on the native side.YetAnotherHttpHandler/src/YetAnotherHttpHandler/ResponseContext.cs
Lines 56 to 60 in 1f499bc
Here is the example.
If I call multiple requests concurrently with larger response body than
pauseWriterThreshold
(64KiB) and intentionally cause backpressure by not reading the stream, the subsequent request stops progressing and times out in the middle. This can be problematic when there are large numbers of concurrent requests.Solution
I have found that if I make a change that allows
PipeWriter.FlushAsync()
to be awaited asynchronously, it passes the same test.This PR adds a
ResponsePipeOptions
property toYetAnotherHttpHandler
and allows it to wait forPipeWriter.FlushAsync()
asynchronously.