+-

考虑一个带有以下端点的.Net Core 3.1 API
GET : 计算 - 执行一个CPU密集型计算任务。 GET:直播检查计算端点的高负载:当'计算'端点有高负载时,每秒300个请求,其他端点会因为所有线程被用完而变慢。
在高负载期间,调用'livecheck'端点会在5-10秒内返回一个请求,这太多了。
这是一个问题,因为如果'livecheck'端点没有按时响应,应用就会被杀死。(AWS ECS,当livecheck时间超过5秒时,就会杀死容器)
是否可以通过在一个单独的线程池上运行 "计算 "端点来确保 "livecheck "端点仍然返回数据。这样,它就不会用掉所有的工作线程,而这些线程可以用于其他端点?
注意。
'computation'必须作为同一个请求的一部分来返回,不要把它排到后台任务。任何其他解决方案也欢迎。
0
投票
投票
我建议将 "cpu密集型计算 "卸载到另一个应用中,而不是和实时检查在同一个应用中完成。可以发送一条异步消息来触发计算处理开始,而应用程序可以从处理应用程序中订阅一个完成或失败的事件。这样大量的处理就不会影响到web api的响应时间。
比这更好的是,你可以把应用docker化。
0
投票
投票
扩展一下我在问题下的评论
我还是建议你按照 避免屏蔽电话的最佳做法.
但现在,让我们假设你 真的 不能,那么你至少应该卸载 计算 在适合的时候从线程中移除,以便让处理器有时间处理 现场检查.
考虑这个例子。
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
如果offload 计算 从线程。
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
輸出通常是: 权衡 这里是单次运行的计算会比同步版慢。