"Too many open files"和请求缓冲



我们有一个ASP.NET Core 5应用程序在AWS的Docker容器中运行。

当它接收到一系列HTTPPOST请求时,我在日志中得到以下错误:

System.IO.IOException: Too many open files
at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String path, OpenFlags flags, Int32 mode)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.CreateTempFile()
at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c_DisplayClass0_0.<<CreateBinderDelegate>g_Bind|0>d.MoveNext()

通过上面的异常跟踪,我们可以看到:

  1. 这发生在MVC中间件中(这是在它到达我们自己的控制器代码之前(
  2. FileBufferingReadStream在读取输入流时试图在磁盘上创建一个新文件时,就会发生这种情况(请参阅此处的源代码(。当您在解决方案中启用缓冲时,就会调用此函数

到目前为止,我们所拥有的是:解决方案中启用了缓冲功能,这导致我们每次收到长正文的请求时都要写入磁盘(大多数情况下都会发生(。但是,我已经从我的解决方案中删除了所有调用EnableBuffering的代码。库/框架中是否有任何代码可以从我们那里启用缓冲?这是由一些环境变量控制的吗?这些变量可能是它运行环境的一部分?

编辑:

这是我的Program.cs类(为了隐私起见,我省略了一些内容(:

public static async Task Main(string[] args)
{
var webHost = CreateHostBuilder(args).Build();
await webHost.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.AddDebug();
logging.SetMinimumLevel(LogLevel.Information);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.CaptureStartupErrors(false);
webBuilder.UseSentry();
})
.ConfigureServices(services => { });
}

这是我的Startup.cs类:

public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
private IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<Config>(Configuration.GetSection("AppSettings"));
services.AddApiVersioning(version =>
{
version.DefaultApiVersion = new ApiVersion(1, 0);
version.AssumeDefaultVersionWhenUnspecified = true;
version.ReportApiVersions = true;
});
services.AddLogging();

//... DI config here
services.AddControllers();
services.AddHealthChecks();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo {Title = "MyApp", Version = "v1"});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IMainIndexer elastic)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHealthChecks("/healthcheck", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
endpoints.MapGet("/",
async context =>
{
await context.Response.WriteAsync(
"<html><body>Welcome to MyApp</body></html>");
});
});
}
}

我们已经尝试了一些解决方案,比如使用不同的Docker基本映像,使用Newtonsoft而不是System.Text,但我们仍然会遇到同样的问题。我是不是错过了什么?

如问题中所述,该问题是由启用请求缓冲的中间件中的某些东西引起的。

我们发现这是哨兵造成的。

你可以在这里看到哨兵呼叫EnableBuffering()

当我们从Program.cs中删除该行时

WebBuilder.UseSentry();

并再次运行相同的负载,错误消失了。

最新更新