c# - 长时间运行的计算 .net 核心的性能问题 - 单独的线程池
问题描述
考虑具有以下端点的 .Net Core 3.1 API
- GET : /computation - 执行 CPU 密集型计算任务
- 获取:/livecheck
/computation 端点上的高负载:当“/computation”端点上的负载很高时,每秒 300 个请求,其他端点会因为所有线程都用完而减慢。
在高负载期间调用“/livecheck”端点将在 5-10 秒内返回一个请求,这太多了。
这是一个问题,因为如果“/livecheck”端点没有按时响应,应用程序就会被杀死。(AWS ECS,当 livecheck 超过 5 秒时会杀死容器)
是否可以通过在单独的线程池上运行“/computation”端点来确保“/livecheck”端点仍然返回数据。这样它就不会用完所有工作线程并且它们可用于其他端点?
笔记 :
- '/computation' 必须作为同一请求的一部分返回,不希望将其排入后台任务。
任何其他解决方案也欢迎。
解决方案
扩展我有问题的评论
我仍然建议您遵循最佳做法以避免阻塞呼叫。
但是现在,让我们假设你真的不能,那么你至少应该从线程中卸载计算,只要它适合给处理器时间livecheck。
考虑这个例子:
void Computation()
{
for (var i = 0; i < 300; i++)
{
Thread.Sleep(1);
}
}
void LiveCheck()
{
Console.WriteLine("I'm alive.");
}
async Task Main()
{
var tasks = new List<Task>();
// Create 1000 blocking compuations to simulate busy thread pool
// or thread pool starvation
for (int i = 0; i < 1000; i++)
{
tasks.Add(Task.Run(Computation));
}
// Simulate 3 seconds after thread pool is busy, execute livecheck
Thread.Sleep(3000);
var sw = Stopwatch.StartNew();
await Task.Run(LiveCheck);
sw.Stop();
Console.WriteLine($"LiveCheck completed in {sw.Elapsed.TotalSeconds} seconds");
await Task.WhenAll(tasks);
}
大多数情况下,我机器上的返回结果是这样的:
LiveCheck completed in 31.2030817 seconds
如果从线程卸载计算:
async Task Computation()
{
for (var i = 0; i < 300; i++)
{
Thread.Sleep(1);
// Yield thread every 50ms
if ((i % 50) == 0)
{
await Task.Yield();
}
}
}
输出通常是:
LiveCheck completed in 2.4753268 seconds
这里的权衡是单次计算将比同步版本慢。
推荐阅读
- php - 如何在没有表格的情况下连续获取我的表格数据
- c - 字符串和 isdigit 函数
- python-3.x - 如何计算环状形状内的内部面积(像素数)?
- python - Python - 根据列条件对值求和
- sql-server - Visual Studio 2019 MSSQL 数据库登录失败(权限问题)
- python - 使用参考列将列数据复制到新工作表
- python - 如何在打破内部功能的同时访问外部功能?
- javascript - 如何用 cookie 隐藏 div
- intellij-idea - 如何在idevim中为IntelliJ获取绝对行号和相对行号?
- sql - 希望在 2+ 列中使用 DIFFERENCE() 查找重复项