如何使用异步调度程序,SemaphorSlim等来限制异步I / O操作和/或它们的延续的并发,有很多答案。我的问题是:这样做有意义吗在标准的ASP.NET MVC / WebAPI方案中?
我们有一个典型的企业API,可作为面向客户的SPA的后端。许多API请求涉及调用数十个下游Web服务,到目前为止,我们已经将它们转换为使用TAP的异步I / O(异步/等待)。这些远程服务调用中有许多是并行启动的,无需等待,然后使用Task.WhenAll
批量等待。有时,当AllAll完成了固定数量的任务后,有时我们启动了远程调用集合中的每个项目-这会导致产生未知数量(但通常少于一打)的任务,然后等待他们与WhenAll。
As I understand,这会导致这些任务的继续(即反序列化其响应的逻辑)被安排在ThreadPool上。这就引出我的问题:并行运行这些受CPU约束的连续操作不会对ThreadPool造成过多压力吗?我们是否应该开发某种中间件来限制单个请求中启动的异步I / O任务的连续性的并发,方法是将它们调度到自定义调度程序中?
通过减少任何给定请求分配的ThreadPool线程数,可以允许我们的应用程序具有更好的可扩展性,这将允许在我们开始耗尽ThreadPool线程(或受到限制)之前为更多的并发请求提供服务通过ThreadPool增长)?
这还是没有用,我们应该简单地相信默认的ThreadScheduler + ThreadPool能够在任意数量的并发请求中将所有任务调度到可用的CPU内核上的功能?
在一个非常大的公司中,这是一个相当成熟的系统,在美国一个州的生产中,它受到数十位专家(包括我自己)的严格审查,即将在全国范围内投入生产。我们自己显然已经想到了诸如“首先采取措施”,“知道您是IO还是CPU限制”,“尝试AppInsights”和“不要比微软更聪明”之类的建议。我们正在寻求的指导级别更像是:这里的任何人是否在美国国家一级实现了全异步ASP.NET Web API系统,并具有异步/ WhenAll并发的现实经验?
答案 0 :(得分:6)
@ tarun-lalwani在评论中提出了一些要点
但是,我将提到永远不要进行优化的可靠建议。如今的中型台式机可以轻松处理16个线程池(通常可以处理数百个等待的任务),好的服务器可以处理更大的线程池,那么您的时间成本与更换成本还是多少?新服务器,大概不到6个月,很可能不到3个月。
任何性能问题都归结为瓶颈,系统只能以最慢的瓶颈速度运行。因此,在实际系统中,改善那些特定的瓶颈是提高性能的方法。如何解决这些瓶颈组是如何提高可伸缩性。台式机和服务器硬件之间仍然存在许多差异,因此我再次强调,在投入数周/数月的时间来解决“问题”之前,您需要查看这些方面的实际非体外指标。可能不在那里。
如上所述的GraphQL允许您重新安排出现瓶颈的位置,使您可以更均匀地分布它们,以更好地利用现有硬件。许多更现代的设计模式也是如此。
总而言之,只有在出现问题时才限制进程。