c# - 如何限制 ASP.NET 中每个请求的内存使用量?

标签 c# asp.net .net .net-core memory-management

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

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

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

最佳答案

.NET CORE 和 .NET 5

因为问题是关于 .Net Core,所以我必须说明为什么走 AppDomain 路线行不通。

App Domains

Why was it discontinued? AppDomains require runtime support and are generally quite expensive. While still implemented by CoreCLR, it’s not available in .NET Native and we don’t plan on adding this capability there.

What should I use instead? AppDomains were used for different purposes. For code isolation, we recommend processes and/or containers. For dynamic loading of assemblies, we recommend the new AssemblyLoadContext class.

Source: Porting to .NET Core | .NET Blog

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

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

要测量其他进程内存,我们可以使用 Process 句柄并获取其 WorkingSetPrivateMemoryVirtualMemory >。 More 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

关于c# - 如何限制 ASP.NET 中每个请求的内存使用量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66937904/

相关文章:

c# - 无法将两个docker、一个数据库、一个.net core应用程序连接在一起

.net - 为什么 RSACryptoServiceProvider.Encrypt() 输出不稳定?

c# - Gridview PageIndex 在 page_Load 事件上未更改

javascript - ItemTemplate 中文本框的 onkeypress 事件不会在 chrome 和 firefox 上触发

c# - 如何使函数对方法私有(private)?

asp.net - Ajax 控制工具包 AsyncFileUploader 控制和 viewstate/session 问题

c# - 如何在 ASP.NET MVC 5 中获取外部登录的电子邮件地址

.NET MVC 购物车

c# - C#5.0的哪些特性可以编译运行在.net 4.0上

c# - 使用 XML 序列化反序列化数组时不期望元素