如何解决如何在 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
句柄并获取其 WorkingSet
、PrivateMemory
和 VirtualMemory
。 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
您需要使用进程(在作业对象或 cgroup 中),在 .NET 中的应用程序级别无法做到这一点。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。