假设您有一个接收请求的Web服务器。现在,每个请求都连接到一个用户会话。现在,在请求中执行的代码是异步的,并使用并行执行和多线程处理,例如Task.Run()
,async await
或Parallel.ForEach
。
现在可以观察到的是,对于某个会话,触发的请求比其他请求更沉重,并使用更多的并行任务。结果是,对于具有繁重操作的请求,单个会话几乎可以使执行任务的所有线程都执行。通过捕获更多任务,其他会话请求会变慢。对于某些会话,服务器看起来非常快(那些首先获得线程的服务器),而对于其他会话,它看起来很慢,在最坏的情况下甚至没有响应。我想要保持某种平衡,以便为会话分配的线程数是均匀分布的
如何解决该问题?
我认为这很有意义。请确认或告诉我为什么您不同意:
很可能我还没有想到其他选择。请帮助我找到解决此问题的正确措辞。如果您能引导我找到解决方案(通过概念上解决或避免问题的方式),我也将非常高兴。
答案 0 :(得分:1)
另一种选择是将优先级用于每个会话提交的任务。您可以为每个会话设置优先级值,在会话开始时,提交的任务将具有较高的优先级,从会话提交的任务越多,优先级将越低。这样,如果会话提交大量任务,则新会话可以为其启动任务分配执行时间,因为它具有更高的优先级。 (*)
尽管如果从会话提交的启动任务是繁重的任务,这将花费大量时间,但是这种方法无法处理这种情况。 (就像您的第一个选择一样,如果您可以检测到长时间运行的任务,则可以给它们较低的优先级)
MSFT提供了您应该检查的QueuedTaskScheduler实现。 source code和article
(*)这种方法的另一个变体是;每个优先级可以有自己的ThreadPool,更高优先级的ThreadPools可以包含比低优先级更多的线程。
答案 1 :(得分:0)
两个可能的选项:
1)创建机器分离,以便长时间运行的任务运行一台单独的机器,并且可以与接收请求和响应请求的Web服务器分开扩展。
2)处理亲和力。重写长时间运行的方法以将相同的线程ID作为目标,以延长等待时间。例如。如果您有2核机器。仅将cpu 2分配给长时间运行的任务,以便仍然可以在cpu 1上处理正常的请求。这将很困难,但无需扩展到新计算机即可使用。