作者:lobtao | 来源:互联网 | 2022-12-11 20:58
关于如何限制异步I/O操作和/或它们的延续的并发性有很多答案 - 使用自定义调度程序,SemaphorSlim等.我的问题是:在标准ASP.NET MVC中执行此操作是否有意义/WebAPI场景?
我们有一个典型的企业API,作为面向客户的SPA的后端.许多API请求涉及调用许多下游Web服务,我们现在通常使用TAP(async/await)将其转换为异步I/O. 许多远程服务调用是并行启动的,无需等待,然后等待批量使用Task.WhenAll
.有时WhenAll是在一定数量的任务上完成的,有时我们会在集合中为每个项目启动一个远程调用- 这会导致产生一个未知(但通常是低,十几个)的任务,然后用WhenAll等待它们.
据我所知,这会导致这些任务的延续(即反序列化其响应的逻辑)在ThreadPool上进行调度.这导致了我的问题:并行运行这些CPU绑定的延续不会导致ThreadPool上的压力过大?我们是否应该开发某种中间件,通过将它们安排到自定义调度程序来限制在单个请求中启动的异步I/O任务的延续的并发性?
通过减少任何给定请求分配的ThreadPool线程的数量,这将允许我们的应用程序更好的可伸缩性,这将允许在我们开始耗尽ThreadPool线程之前提供更多的并发请求(或者被ThreadPool限制增长)?
或者这是相当无用的,我们应该简单地相信默认的ThreadScheduler + ThreadPool能够将所有任务安排到可用的CPU核心上,无论多少并发请求?
每个人都试图回答:
这是一个非常大的公司的一个相当成熟的系统,由几十位专家(包括我自己)仔细审查,在一个美国州的生产中,即将进入国家层面的生产.诸如"先测量","知道你是否与CPU绑定","尝试AppInsights"和"不要试图比微软更聪明"等建议是我们自己明显想到的第一件事.我们正在寻求的指导级别更像是:有没有人在美国国家层面实现了一个全异步的ASP.NET Web API系统,并且拥有async/WhenAll并发的真实体验?
1> Thymine..:
@ tarun-lalwani在评论中提出了一些很好的观点
但我会提到坚实的建议,永远不要优先考虑.今天的中端桌面可以轻松处理16的线程池(通常可以处理数百个等待任务),一个好的服务器可以处理比这更大的线程池,你的时间成本与替换成本相比多少或者新服务器,可能不到6个月,很可能不到3个月.
任何性能问题都归结为瓶颈,系统只能执行最慢的瓶颈.因此,在现实世界系统中,改善这些特定瓶颈的方法是如何提高性能.如何扩展这些瓶颈是如何提高可扩展性的.桌面和服务器硬件之间仍然存在很多差异,因此我再次强调,在花费数周/数月的时间来解决"问题"之前,您需要查看真实世界的非体外指标.可能不在那里.
如上所述的GraphQL允许您重新安排瓶颈发生的位置,允许您更均匀地分配它们,以更好地利用您已有的硬件.许多更现代的设计模式也是如此.
总之,限制一个过程,只要它成为一个问题,它才有意义.