微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 ASP.NET 中限制每个请求的内存使用量? .NET 核心和 .NET 5应用域如何测量单独进程的内存使用情况替代方法

如何解决如何在 ASP.NET 中限制每个请求的内存使用量? .NET 核心和 .NET 5应用域如何测量单独进程的内存使用情况替代方法

我有一个在 ASP.NET 中运行的多租户 .NET 5 应用程序,其中一个请求可以运行任意代码并使用任意数量的内存。如何针对每个请求防止用户使用过多内存?

我知道我可以限制每个进程,也可以限制发出的 HTTP 请求的大小,但这不是我需要的。我需要一种方法,如果用户运行像 int array = int[1,000,000] 这样的代码,他们会得到一个异常,而不是整个网站都关闭了。

编辑:这是一个 jsfiddle 风格的应用程序(具体来说,它是darklang.com),虽然使用自定义语言和运行时,所以我对运行时有很好的控制。

解决方法

.NET 核心和 .NET 5

因为问题是关于 .Net Core,所以我必须说明为什么去 AppDomain 路由不起作用。

应用域

为什么停止使用? AppDomains 需要运行时支持并且通常非常昂贵。虽然仍由 CoreCLR 实现,但它在 .NET Native 中不可用,我们不打算在那里添加此功能。

我应该使用什么? AppDomains 用于不同的目的。对于代码隔离,我们推荐进程和/或容器。对于程序集的动态加载,我们建议使用新的 AssemblyLoadContext 类。

Source: Porting to .NET Core | .NET Blog

如果您想获得有关内存使用情况的“自动”信息,那么我们只有一种方法可以做到这一点。

如何测量单独进程的内存使用情况

要测量其他进程的内存,我们可以使用 Process 句柄并获取其 WorkingSetPrivateMemoryVirtualMemoryMore about memory types

处理另一个进程的代码非常简单。

private Process InterpreterProcess;

// Run every how often you want to check for memory
private void Update()
{
    var workingSet = InterpreterProcess.WorkingSet64;
    if(workingSet > Settings.MemoryAllowed)
    {
        InterpreterProcess.Kill(true);
    }
}

private void Start()
{
    InterpreterProcess = new Process(...);
    // capture standard output and pass it along to user
    Task.Run(() =>
    {
        Update();
        Thread.Sleep(50);
        // This will be also convenient place to kill process if we exceeded allowed time
    });
}

然而,这给我们留下了一个非常重要的问题,因为我们可能允许用户访问系统关键资源 - 即使我们没有在进程上运行管理员权限。

替代方法

既然您提到您有一个自定义解释器,那么您可能更容易为解释器添加内存管理、内存计数和安全性。

由于我们可以假设内存分配仅使用 new 进行,因此您的解释器只需测试每个新分配的大小并相应地进行测试。

要测试托管对象的大小,您需要“分析”创建的实例并在每个简单类型上使用 sizeof(),正确的方法是制作 There's no way to get the managed object size in memory #24200

,

您需要使用进程(在作业对象或 cgroup 中),在 .NET 中的应用程序级别无法做到这一点。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。