ASP.NET Core 禁用请求缓冲(不是响应缓冲)

gbu*_*ton 6 .net out-of-memory asp.net-core

我找到了一个很好的控制响应缓冲的答案。但我需要禁用请求缓冲。

问题的简短版本:

我发现后台有一个缓冲区,里面填满了请求数据。断点请求方法不会暂停这个过程,所以它显然是由后台线程完成的。我遵循了一些说明(例如关闭 FormValueProviderFactory),但它们并不能阻止这种行为。

长版问题:

我已经在这里实现了代码。

该示例创建了一个名为 DisableFormValueModelBindingAttribute 的过滤器属性,文档声称该属性可防止将文件加载到内存中,但它没有这种效果。在请求开始流式传输后过滤器被命中。

但是我发现整个请求仍然缓冲到内存中。它达到请求内存限制并开始存储在磁盘中,但这会导致服务器磁盘空间不足。由于服务托管在 docker 中,我只有几百 MB 可以使用。我真正需要的是将多部分请求缓冲到我可以读取它的程度

我正在使用 .net core 2.1 和 AspNetCore 2.1.1

关于 Request.EnableBuffering 的说明

名称不正确 - 请求总是被缓冲,这实际上是启用请求回滚。

关于 IHttpBufferingFeature.DisableBuffering 的说明

这是过时的。它没有实现细节。过时的标签说

[Obsolete("See IHttpRequestBodyFeature or IHttpResponseBodyFeature DisableBuffering", error: true)]
Run Code Online (Sandbox Code Playgroud)

但 IHttpRequestBodyFeature不存在。

令人失望,因为当这个答案出现时我很兴奋!

更多信息

经过一些实验,我想出了一些事情。我将请求从控制器移到中间件中。

[Obsolete("See IHttpRequestBodyFeature or IHttpResponseBodyFeature DisableBuffering", error: true)]
Run Code Online (Sandbox Code Playgroud)

但是我发现有一个后台线程填充了请求缓冲区。我在中间件内设置了一个断点,但我仍然可以看到后台发生的上传。请求缓冲区仍在填充。

答案可能与可以对 HttpRequestFeature 进行的可能配置有关。

更多信息

在 UseKestrel 的回调中,您可以配置限制并且有一个限制

称为“MaxRequestBufferSize”

但默认为 1MB。很明显,它不对缓冲到磁盘的完整请求负责。

我还发现了一个关于缓冲可配置的 github 问题,主要是抱怨它不是。这并没有让我充满信心。

vvv*_*v4d 1

在撰写本文时,这是不可能的。

IHttpRequestBodyFeature未实现或公开,因此没有可用于我们调用来禁用请求缓冲的方法。只有一种方法可以使用以下方法在IHttpResponseBodyFeature中禁用响应缓冲DisableBuffering中禁用响应缓冲。

我在 GitHub 上进行了搜索,发现IHttpRequestBodyFeature https://github.com/search?q=IHttpRequestBodyFeature&type=的结果很少,进一步支持了该接口尚不可用或尚未向我们公开的想法。如果你搜索IHttpResponseBodyFeature另一方面,

我建议提交一个问题,因为 IHttpRequestBodyFeature此处不可用: https ://github.com/dotnet/aspnetcore/issues

我找不到禁用请求缓冲的方法IHttpResponseFeature。没有method规定这样做。然而,IHttpResponseBodyFeature有一个method可以禁用响应缓冲;下面是一个例子:

  1. 添加以下命名空间

    using Microsoft.AspNetCore.Http.Features;

  2. 在您想要禁用响应缓冲的IActionResults中,使用 以下方法:DisableBuffering()

选择退出响应的写入缓冲

var bufferingFeature2 = HttpContext.Features.Get<IHttpResponseBodyFeature>();
bufferingFeature2?.DisableBuffering();
Run Code Online (Sandbox Code Playgroud)