c# - 从 ASP.NET Core 3.1 端点流式传输数据而不消耗大量内存

标签 c# asp.net-core asp.net-core-webapi

编辑: 我有一个诊断中间件组件,可以将响应提取到跟踪文件中。那是罪魁祸首。所以,如果你发现这个是因为你遇到了我遇到的同样问题:检查你的中间件!

因此,在调用 Web API 端点时,我以流式异步方式从各种数据源收集了大量数据(> 100 MB)。我想以流式传输方式将该数据转发给客户端。

为此,我构建了自己的 IActionResultExecutor<T>概括这一点,因为我们有一些这样的端点。

但是我注意到整个响应在实际发送到客户端之前缓存在内存中。不好。显然,我做错了什么,但我无法理解我做错了什么!

执行者的ExecuteAsync看起来像这样:

public async Task ExecuteAsync(ActionContext context, AsyncStreamResult result)
{
   var bufferingFeature = context.HttpContext.Features.Get<IHttpResponseBodyFeature>();
   if (bufferingFeature != null)
      bufferingFeature.DisableBuffering();

   context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
   context.HttpContext.Response.ContentType = "application/json; charset=utf-8";

   var cancellationToken = context.HttpContext.RequestAborted;
   await context.HttpContext.Response.StartAsync(cancellationToken);
   await context.HttpContext.Response.WriteAsync("[", cancellationToken);
   bool seenFirstItem = false;

   await foreach (var item in result.Data) {
      if (seenFirstItem)
         await context.HttpContext.Response.WriteAsync(",", cancellationToken);

      await context.HttpContext.Response.BodyWriter.WriteAsync(item.JsonBytes, cancellationToken);

      seenFirstItem = true;
   }

   await context.HttpContext.Response.WriteAsync("]", cancellationToken);
}

我可以看到整个过程如何在 Visual Studio 中以线性方式分配大量内存。我还可以看到 curl 在请求完成之前没有获取任何数据。然后一切都一气呵成。具有讽刺意味的是,curl 报告数据的传输编码是 chunked .那是一大块!一些数据流超过 100 MB,仅出于这个原因,我买不起 k8s 集群中的强大 pod。在我看来,这个操作应该生成一堆 Gen 0 对象,但没有什么是 GC 不能处理的。引用的对象应该以千字节为单位!

我试过撒一些 await context.HttpContext.Response.BodyWriter.FlushAsync(cancellationToken) , 但似乎没有任何区别。

我做错了什么?

最佳答案

问题已解决:我在管道中有一些调试日志记录中间件,它打开缓冲以跟踪发送给客户端的响应。卫生部!

关于c# - 从 ASP.NET Core 3.1 端点流式传输数据而不消耗大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61056100/

相关文章:

c# - Visual Studio 设计器中窗体的大小是否受限于屏幕分辨率?

c# - CreateLogger() 之前被调用过,只能调用一次

docker - 适用于无身份的 ASP.NET Core WebAPI 的 Sustainsys SAML2 示例

c# - 服务器端 SignalR 连接在长时间正常运行后失败

c# - .Net 哈希代码不再持久?

c# - 等待持久实体值发生变化

c# - .NET XML 序列化数组/列表对象别名

azure - 将 FFMpeg 与 Asp .Net Core 和视频流一起使用

c# - 超时后阻止来自 C# NetworkStream 的传入数据

asp.net-core - Web API 端点不是来自 postman 而是来自 swagger