C# 由于系统中打开的文件太多,ASP.NET core 2.2崩溃

C# 由于系统中打开的文件太多,ASP.NET core 2.2崩溃,c#,linux,sockets,.net-core,cloud-foundry,C#,Linux,Sockets,.net Core,Cloud Foundry,我们的应用程序运行在cloud foundry服务器上,几周后我们遇到以下异常: System.Net.Http.HttpRequestException:系统中打开的文件太多--System.Net.Sockets.SocketException:系统中打开的文件太多,位于System.Net.Sockets.Socket..ctor(AddressFamily AddressFamily,SocketType SocketType,ProtocolType ProtocolType)的Sys

我们的应用程序运行在cloud foundry服务器上,几周后我们遇到以下异常:

System.Net.Http.HttpRequestException:系统中打开的文件太多--System.Net.Sockets.SocketException:系统中打开的文件太多,位于System.Net.Sockets.Socket..ctor(AddressFamily AddressFamily,SocketType SocketType,ProtocolType ProtocolType)的System.Net.Sockets.DualSocketMultipleSeconnectAsync(SocketType SocketType,ProtocolType ProtocolType)位于System.Net.Sockets.Socket.ConnectAsync(SocketType SocketType,ProtocolType ProtocolType,SocketAsyncEventArgs e)的System.Net.Http.ConnectHelper.ConnectAsync(字符串主机,Int32端口,CancellationToken CancellationToken)

如果我在容器中检查套接字,会有很多套接字转储,并且它们的数量会快速增加(参见上图)

我在容器中的呼叫:

lsof | grep 'sock'
更新:

现在我已经发现,应用程序的哪个部分导致了这个问题,但我不知道为什么:

为了从客户端为地图层调用外部API,我在后端创建了一个代理:

    public static IApplicationBuilder UseMapLayerProxy(this IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            var config = (app.ApplicationServices.GetService(typeof(IOptions<AppSettings>)) as IOptions<AppSettings>).Value.MapServer;
            if (IsMapLayerRequest(context, config))
            {
                var forwardedHost = context.Request.Headers["X-Forwarded-Host"].ToArray().FirstOrDefault();
                if (forwardedHost == null)
                {
                    context.Request.Headers.Add("X-Forwarded-Host", context.Request.Host.ToString());
                }

                var builder = app.New(); // branch app to lose all middlewares and prevent infinity recursion
                builder.RunProxy(new ProxyOptions
                {
                    Scheme = config.Scheme,
                    Host = config.Host,
                });
                await builder.Build().Invoke(context);
            }
            else
            {
                await next.Invoke();
            }
        });

        return app;
    }

    private static bool IsMapLayerRequest(HttpContext httpContext, MapServerSettings config)
    {
        return Array.Exists(config.LayerPaths, path => httpContext.Request.Path.Value.StartsWith(path, StringComparison.OrdinalIgnoreCase));
    }

更新2

我已经更改了代理的代码,现在它运行良好。但我不确定这是否是实现条件反向代理的正确方法(取决于请求url)。是否有更好的方法

    public static IApplicationBuilder UseMapLayerProxy(this IApplicationBuilder app)
    {
        var config = (app.ApplicationServices.GetService(typeof(IOptions<AppSettings>)) as IOptions<AppSettings>).Value.MapServer;
        app.MapWhen(
            (httpContext) =>
            {   
                if (IsMapLayerRequest(httpContext, config)) {
                     httpContext.Request.Headers.Add("Authorization", "Basic BASE64_PW");
                }

                return IsMapLayerRequest(httpContext, config);
            },
            builder => builder.RunProxy(new ProxyOptions
            {
                Scheme = config.Scheme,
                Host = config.Host,
            }));

        return app;
    }

    private static bool IsMapLayerRequest(HttpContext httpContext, MapServerSettings config)
    {
        return Array.Exists(config.LayerPaths, path => httpContext.Request.Path.Value.StartsWith(path, StringComparison.OrdinalIgnoreCase));
    }
公共静态IApplicationBuilder UseMapLayerProxy(此IApplicationBuilder应用程序)
{
var config=(app.ApplicationServices.GetService(typeof(IOptions))作为IOptions.Value.MapServer;
app.MapWhen(
(httpContext)=>
{   
if(IsMapLayerRequest(httpContext,config)){
httpContext.Request.Headers.Add(“授权”、“基本BASE64_PW”);
}
返回IsMapLayerRequest(httpContext,config);
},
builder=>builder.RunProxy(新的代理选项
{
Scheme=config.Scheme,
Host=config.Host,
}));
返回应用程序;
}
私有静态bool IsMapLayerRequest(HttpContext HttpContext,MapServerSettings配置)
{
return Array.Exists(config.LayerPaths,path=>httpContext.Request.path.Value.StartsWith(path,StringComparison.OrdinalIgnoreCase));
}

好吧,这肯定是资源不足的问题。使用http客户端的代码怎么样,响应也被清理了吗?@FrankNielsen我已经更新了代码。希望它有帮助吗?是否可以关闭这个
IsmaPayerRequest
问题,或者避免该路径-用于测试?我猜断开该链可能会导致错误sing socket cleanup。我在这里猜测。由于您正在执行一个
var builder=app.New();
,可能app.ServiceProvider中的所有服务都必须在新服务之前处理。我猜
var builder=app.New();
正在创建一个新的服务范围。看起来正确,而且更简单:)
    public static IApplicationBuilder UseMapLayerProxy(this IApplicationBuilder app)
    {
        var config = (app.ApplicationServices.GetService(typeof(IOptions<AppSettings>)) as IOptions<AppSettings>).Value.MapServer;
        app.MapWhen(
            (httpContext) =>
            {   
                if (IsMapLayerRequest(httpContext, config)) {
                     httpContext.Request.Headers.Add("Authorization", "Basic BASE64_PW");
                }

                return IsMapLayerRequest(httpContext, config);
            },
            builder => builder.RunProxy(new ProxyOptions
            {
                Scheme = config.Scheme,
                Host = config.Host,
            }));

        return app;
    }

    private static bool IsMapLayerRequest(HttpContext httpContext, MapServerSettings config)
    {
        return Array.Exists(config.LayerPaths, path => httpContext.Request.Path.Value.StartsWith(path, StringComparison.OrdinalIgnoreCase));
    }