Unable to stream using HTTP service invocation
- Dominant language
- C#
- Stars
- 1.2k
- Forks
- 378
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 6
Description
I am attempting to configure and setup HTTP streaming via service to service communication. We have `ServiceA` which calls a streaming HTTP endpoint on `ServiceB` through dapr. We are using dapr 1.13 so our understanding is that streaming should be enabled by default.
Following the example from [InvokeServiceHttpClientExample.cs](https://github.com/dapr/dotnet-sdk/blob/ad3350f70ebca14cdad5f3bdff5c1b4c6a1bf890/examples/Client/ServiceInvocation/InvokeServiceHttpClientExample.cs) we are attempting to use dapr HTTP client to call the streaming endpoint on `ServiceB`. To keep things simple, we have setup a dummy `TestPing` route on `ServiceB` which should stream back 10 items at 500ms intervals.
Minimal Code Sample of `ServiceA`
```
var client = DaprClient.CreateInvokeHttpClient(GetDaprAppId());
var sw = Stopwatch.StartNew();
var responseStream = await client.GetStreamAsync(GetPingUriFixed());
var items = JsonSerializer.DeserializeAsyncEnumerable(responseStream, new JsonSerializerOptions { DefaultBufferSize = ItemSize / 2 });
if (sw.ElapsedMilliseconds > Delay * ItemCount)
throw new InvalidOperationException($"Initial request to took {sw.ElapsedMilliseconds} which is greater than (delay * itemCount) {Delay * ItemCount} which indicates streaming was unsuccessful");
```
Minimal Code Sample of `ServiceB` endpoint:
```
public IActionResult PingStreamFixed()
{
var delay = 500;
var itemCount = 10;
var itemSize = 10 * 1024;
return Ok(GetResult());
async IAsyncEnumerable GetResult()
{
for (var i = 0; i < itemCount; i++)
{
await Task.Delay(delay);
var item = new byte[itemSize];
Random.Shared.NextBytes(item);
yield return Convert.ToBase64String(item);
}
}
}
```
When running this code we find that the response takes 5 seconds to return OK (500ms delay * 10 itemCount) which indicates that streaming is not occurring.
To troubleshoot, we added portforwards on `ServiceB` as well as `ServiceB`'s dapr sidecar and called the streaming endpoint from a browser to confirm that our test endpoint streams as expected.
When calling the `ServiceB` streaming endpoint via the browser, we successfully see an initial response, then stream the remaining items in 500ms intervals which is our expected behavior.
Request: `http://localhost:8080/cluster/test/pingStreamFixed`

However, when we call the endpoint through `ServiceB`'s dapr sidecar, we see that we only get a single, non-streamed response after a full 5 seconds.
Request: `http://localhost:3500/v1.0/invoke/ep--00000000-0000-0000-0000-000000000000/method/cluster/test/pingStreamFixed`

## Question:
It seems our test streaming endpoint behaves as expected and streams when calling our service directly, but not through the dapr sidecar. We have been unable to find any additional examples or documentation to help us get this to work. Is there some sidecar configuration or setting on the daprClient that we are missing to get streaming to work correctly?
Contributor guide
Research direction
Start with examples/Client/ServiceInvocation/InvokeServiceHttpClientExample.cs and the minimal ServiceA and ServiceB samples in the issue. Reproduce the call through the Dapr sidecar at the provided /v1.0/invoke URL, then compare it with the direct service request. Done means the client receives the initial response without waiting five seconds and the remaining items arrive at roughly 500ms intervals.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100