我对在ASP.NET MVC中使用异步操作有一些顾虑。它什么时候能提高我的应用程序的性能,什么时候不能
发布于 2015-06-01 14:33:10
当一个操作必须执行几个独立的长时间运行的操作时,异步操作方法非常有用。
AsyncController类的典型用法是长时间运行的
服务调用。
我的数据库调用应该是异步的吗?
与数据库服务器相比,IIS线程池通常可以处理更多的并发阻塞请求。如果数据库是瓶颈,异步调用将不会加速数据库响应。如果没有节流机制,通过使用异步调用将更多的工作有效地分派给不堪重负的数据库服务器,只会将更多的负担转移到数据库上。如果您的数据库是瓶颈,异步调用将不会是魔术子弹。
来自@PanagiotisKanavos的评论:
此外,
并不意味着并行。异步执行将有价值的线程池线程从外部资源阻塞中释放出来,而不会造成复杂性或性能损失。这意味着同一台IIS机器可以处理更多的并发请求,而不是说它会运行得更快。
您还应该考虑阻塞调用是从CPU密集型的spinwait开始的。在压力期间,阻塞调用将导致延迟升级和应用程序池回收。异步调用简单地避免了这个
发布于 2015-06-01 21:16:58
您可能会找到我的MSDN article on the subject helpful;我在那篇文章中花了很多篇幅描述什么时候应该在ASP.NET上使用async
,而不仅仅是如何在ASP.NET上使用async
。
在ASP.NET
中使用异步操作我有一些顾虑。当它提高我的应用程序的性能时,以及何时不是。
首先,要理解async
/await
就是为了释放线程。在GUI应用程序中,它主要是关于释放GUI线程,以便用户体验更好。在服务器应用程序(包括ASP.NET MVC)上,它主要是关于释放请求线程,以便服务器可以扩展。
特别是,它不会:
await
时,它们会完成(只有一点点)对调用者/浏览器的slower.await
只向ASP.NET线程池“让步”,而不向浏览器“让步”。的第一个问题是-在ASP.NET MVC中到处使用异步操作好吗?
我想说在你做I/O的任何地方使用它都是很好的,尽管它可能不一定是有益的(见下文)。
然而,将它用于CPU绑定的方法是不好的。有时开发人员认为他们可以通过在控制器中调用Task.Run
来获得async
的好处,这是一个可怕的想法。因为该代码最终通过占用另一个线程来释放请求线程,所以根本没有好处(事实上,它们正在承担额外线程切换的惩罚)!
当我想要查询数据库(通过EF/NHibernate/其他
)时,我应该使用async/await关键字吗?
您可以使用任何可用的可等待的方法。现在大多数主流软件都支持async
,但也有一些不支持,如果你的对象关系映射不支持async
,那么就不要尝试用Task.Run
或其他类似的东西来包装它(见上)。
请注意,我说的是“你可以使用”。如果您正在讨论只有一个数据库后端的ASP.NET MVC,那么您(几乎可以肯定)不会从async
中获得任何可伸缩性优势。这是因为IIS可以处理的并发请求比单个SQL server实例(或其他传统RDBMS)多得多。然而,如果你的后端更现代- SQL server集群,Azure SQL,NoSQL等等-并且你的后端可以扩展,你的可伸缩性瓶颈是IIS,那么你可以从async
中获得可伸缩性的好处。
第三个问题--在一个单独的操作方法中,我可以使用await关键字异步查询数据库多少次?
你想要多少都行。但是,请注意,许多ORM都有每个连接一个操作的规则。特别是,EF只允许每个DbContext执行一个操作;无论操作是同步还是异步,都是如此。
此外,请再次牢记后端的可伸缩性。如果您正在访问SQL Server的单个实例,而您的IIS已经能够使SQLServer保持满容量,那么加倍或增加两倍的SQLServer压力对您没有任何帮助。
发布于 2015-06-01 14:38:49
在ASP.NET
中到处使用异步操作好吗?
与通常的编程一样,这取决于。当走上一条特定的道路时,总会有一个权衡。
在你知道你会收到对你的服务的并发请求,并且你希望能够很好地向外扩展的地方,async-await
大放异彩。async-await
如何帮助向外扩展?事实上,当您同步调用异步IO调用时,例如网络调用或命中数据库时,负责执行的当前线程将被阻塞,等待请求完成。当您使用async-await
时,您可以让框架为您创建一个状态机,以确保在IO调用完成后,您的方法将从它停止的地方继续执行。
需要注意的是,这个状态机有一个微妙的开销。让一个方法异步并不能让它执行更快的,这是一个需要理解的重要因素,也是许多人的误解。
在使用async-await
时要考虑的另一件事是,它完全是异步的,这意味着您将看到异步贯穿整个调用堆栈。这意味着如果您想公开同步应用编程接口,您经常会发现自己复制了一定数量的代码,因为async和sync不能很好地混合。
当我想要查询数据库(通过EF/NHibernate/其他
)时,我应该使用async/await关键字吗?
如果您选择使用异步IO调用,那么async-await
将是一个很好的选择,因为越来越多的现代数据库提供商公开了实现TAP (任务异步模式)的异步方法。
在一个操作方法中,我可以使用await关键字异步查询数据库多少次?
只要你遵循数据库提供商规定的规则,你想要多少就有多少。您可以进行的异步调用数量没有限制。如果您有相互独立且可以并发执行的查询,则可以为每个查询旋转一个新任务,并使用await Task.WhenAll
等待这两个查询完成。
https://stackoverflow.com/questions/30566848
复制相似问题