.Net Core Web Api异步无关紧要?

Zac*_*son 4 c# asynchronous asp.net-core

我一直用async关键字编写我的Web Api控制器方法,并且一直在使用async.我最近尝试进行方法同步以查看它将如何影响性能,并且发现它对任何其他http请求没有阻塞影响感到震惊.

举例 -

[Route("Foo")]
class FooController {
  [HttpGet("Hello")]
  public string GetHello()
  {
    Thread.Sleep(100000); // 100 seconds
    return "Hello";
  }

  [HttpGet("Goodbye")]
  public string GetGoodbye()
  {
    return "Goodbye";
  }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我可以运行GET=> /Foo/Hello后跟任意数量的GET=>,/Foo/Goodbye并且我对Goodbye端点的请求没有阻塞.

我原本以为我需要让Hello方法异步,以便对Goodbye端点的请求会毫不拖延地返回.但是使这个方法同步/异步没有效果!

非常困惑.Web Api应用程序不需要异步吗?为什么推荐?

dee*_* zg 11

它并不那么简单.

有一种叫做线程池的东西.对您的应用程序的每个请求都会分配从威胁池中获取的单独线程.这是一个请求不阻止另一个请求的第一个原因.

现在,当流量较低时,一切都很好,所以你没有达到线程池中线程的限制数量.但...

为了便于讨论,让我们说你的请求平均需要1秒,并且你有大小= 100的线程池.你将开始体验第101次请求的限制.那个,因为它没有分配给它的线程池,将不得不等待第100个请求完成,将线程释放回线程池然后它可以被处理.

现在,根据您的请求,async可以提供帮助(但也可能导致问题,所以不要盲目使用它!):

  1. 如果您的请求执行I/O操作(网络调用,文件系统,数据库异步等等),那么这些操作将在I/O线程上运行.那些不是来自线程池.因此,想象一下进来的请求,并触发需要0.93秒的nework调用或文件读取.这实际上意味着,如果你不使用异步,你的线程池线程对0.93secs是没有用的,它只是坐在那里等待IO线程完成.在这些情况下,async可能非常有用,因为一旦它命中await关键字(与使用IO线程的操作一起使用),它将立即释放线程池线程,以便可以提供下一个请求.一旦IO操作完成,它将从线程池获取线程以提供响应.

  2. 如果您的请求不使用任何IO操作但强制它们使用异步(有方法可以执行),那么您实际上要做的就是将一个线程池线程(用于获取请求的初始线程)替换为另一个线程池线程(这将需要运行).在这种情况下,您只会创建开销并失去性能.

但是,无论如何,我有一种与你的问题没有严格关系的感觉.在上述两种情况中的任何一种情况下,您的方法都是在2个单独的请求中运行的,几乎async/await与服务器环境无关,而是与服务器环境无关地处理请求.