简体   繁体   English

如何在 ASP.NET 中限制每个请求 memory 的使用?

[英]How to limit per-request memory usage in ASP.NET?

I have a multi-tenant .NET 5 application, running in ASP.NET, in which a request can run arbitrary code and use an arbitrary amount of memory.我有一个多租户 .NET 5 应用程序,在 ASP.NET 中运行,其中一个请求可以运行任意代码并使用任意数量的 memory。 How can I protect against users using too much memory, on a per-request basis?如何防止用户在每个请求的基础上使用过多的 memory?

I'm aware that I can limit per-process, and also that I can limit the size of a HTTP request being made, but that's not what I need.我知道我可以限制每个进程,也可以限制发出的 HTTP 请求的大小,但这不是我需要的。 I need a way that if a user runs code like int array = int[1,000,000,000,000,000,000,000] they will get an exception rather than the entire site coming down.我需要一种方法,如果用户运行像int array = int[1,000,000,000,000,000,000,000]这样的代码,他们将得到一个异常而不是整个站点都崩溃。

Edit: this is a jsfiddle style application (specifically, it's darklang.com), though with a custom language and runtime, so I have pretty good control over the runtime.编辑:这是一个 jsfiddle 风格的应用程序(具体来说,它是 darklang.com),虽然使用自定义语言和运行时,所以我对运行时有很好的控制。

.NET CORE and .NET 5 .NET 核心和 .NET 5

Because the question is about.Net Core I must include why going AppDomain route won't work.因为问题是关于.Net Core 我必须包括为什么去 AppDomain 路线行不通。

App Domains应用程序域

Why was it discontinued?为什么停产了? AppDomains require runtime support and are generally quite expensive. AppDomain 需要运行时支持并且通常非常昂贵。 While still implemented by CoreCLR, it's not available in .NET Native and we don't plan on adding this capability there.虽然仍由 CoreCLR 实现,但它在 .NET Native 中不可用,我们不打算在那里添加此功能。

What should I use instead?我应该改用什么? AppDomains were used for different purposes. AppDomain 用于不同的目的。 For code isolation, we recommend processes and/or containers.对于代码隔离,我们推荐进程和/或容器。 For dynamic loading of assemblies, we recommend the new AssemblyLoadContext class.对于程序集的动态加载,我们推荐新的 AssemblyLoadContext class。

Source: Porting to .NET Core | 来源:移植到 .NET 内核 | .NET Blog .NET 博客

This leaves us only one way to do this if you want to have "automatic" information about memory usage.如果您想获得有关 memory 使用情况的“自动”信息,那么我们只有一种方法可以做到这一点。

How to measure memory usage for a separate process如何测量 memory 对单独进程的使用情况

To measure other process memory we can use the Process handle and get its WorkingSet , PrivateMemory , and VirtualMemory .要测量其他进程 memory 我们可以使用Process句柄并获取其WorkingSetPrivateMemoryVirtualMemory More about memory types 有关 memory 类型的更多信息

The code to handle another process is quite simple.处理另一个进程的代码非常简单。

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
    });
}

This, however, leaves us with a very important question, since we might allow users to access system critical resources - even if we do not run Administrator privileges on the Process.然而,这给我们留下了一个非常重要的问题,因为我们可能允许用户访问系统关键资源——即使我们没有在进程上运行管理员权限。

Alternative approach替代方法

Since you mentioned that you have a custom interpreter it might be easier for you to add memory management, memory counting, and security to the interpreter.既然您提到您有一个自定义解释器,您可能更容易为解释器添加 memory 管理、memory 计数和安全性。

Since we can assume that memory allocation is only made with new your interpreter needs to just test the size of each new allocation and test accordingly.由于我们可以假设 memory 分配仅使用new分配,您的解释器只需测试每个新分配的大小并进行相应测试。

To test managed object size you need to "analyze" created instance and use sizeof() on each simple type, a proper way is in the making There's no way to get the managed object size in memory #24200要测试托管 object 大小,您需要“分析”创建的实例并在每个简单类型上使用sizeof() ,正在制定正确的方法没有办法在 ZCD69B4957F06CD818D7BF3D20980 中获取托管 object 大小

You need to use a process (within a job object or cgroup), there's no way to do this at the application level in .NET.您需要使用一个进程(在作业 object 或 cgroup 中),在 .NET 的应用程序级别无法执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM