之前看过别人提出为什么在本是多线程的Asp.Net下需要异步环境的时候,提出在Asp.Net环境下本身就是多线程,每个请求就是由一个专门IIS线程负责(咱不说Core下无IIS的情况)。所以以此推论Asp.Net下的异步是没有任何意义的,且由于异步的线程上下文保存和上下文切换的原因只会损害性能,百害而无一利。
然后我表示难道你不知道IIS线程是宝贵的线程,而异步线程则是线程池廉价线程,异步提升的是吞吐量而不是响应速度等云云。。。
在此不是要来撕逼,而是以此作为抛砖引玉,翻译一下 Async In C#5第二章节里Web Application Server Code章节里相关内容以此论证在Web里异步是有意义的:
Asp.Net网站服务器没有类似UI线程这样的单线程限制(上一章节里所讨论UI线程的异步).但是在Web里使用异步仍然是有好处的,长时(Long-Running),操作特别是数据库查询,这在Web应用程序里是非常常见的操作
根据IIS的版本不同,Web站点将会有请求处理线程的限制(IIS线程),这将影响正在处理的并发请求数量的总数.如果你的请求需要耗费大量时间等待数据库查询,那么你或许需要增加你的服务器以便处理更多并发而来的请求.
当一个线程被阻塞的时候,它没有使用任何Cpu资源,但你不能假设这个线程没有占用任何服务器资源.实际上阻塞的线程可能会导致两个重大的瓶颈
①内存:
每一个托管线程都需要保留大概1M大小的虚拟内存.这在只有十几条线程的时候不是什么问题.但如果在使用上百条线程的时候这很容易失控.如果内存经常在交换(指内存条里的内存数据交换到硬盘里的虚拟内存文件),在该线程恢复(Resuming)运行的时候将会变得相当慢.
②调度:
操作系统的调度器负责决定哪条线程在什么时间可以被Cpi执行.无论该线程是否被阻塞,调度器都必须要考虑每条线程的情况,去确认它什么时候会变成不阻塞的状态.这个上下文的切换(指各个线程之前来回切换确认状态)是一个缓慢的操作,这将会拖慢整个系统.
上述的问题将直接体现在服务器的延迟增加和吞吐量的下降.
异步代码的主要特征在于,线程启动一个长时(Long-Running)操作后就被释放了然后去做其他事情(比如去处理其他用户的请求).具体到Asp.Net里,线程来源于线程池, 所以它(那条线程)将在那个长时(Long-Running)操作执行期间返回到线程池里去处理其它的请求.所以可以用更少的线程来处理更多的请求.
个人总结:
异步提升的不是性能或者响应时间,而是吞吐量
异步代码理论上应该是比同步代码慢(由于异步作了并行的另当别论),但是能提升服务器的吞吐量我觉得这个是值得的.
另外个人推荐大部分Http请求和可以预测的较慢的Sql请求都应该走异步,这些是我个人认为比较"慢"且比较能体现出异步的意义的使用环节