【问题标题】:.Net Core Web Api Async Doesn't Matter?.Net Core Web Api 异步无关紧要?
【发布时间】:2017-12-11 19:32:31
【问题描述】:

我一直在使用 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";
  }
}

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

我最初认为我需要使 Hello 方法异步,以便对 Goodbye 端点的请求可以立即返回。但是使这个方法同步/异步没有效果!

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

【问题讨论】:

  • ASP.Net Core 使用多线程。
  • 建议在 scale 上运行。当您的 ThreadPool 用完线程、您的网络服务器的队列已满并且请求被拒绝时,小规模的测试不会揭示发生的问题。明智地使用async 意味着您可以只使用少数线程为数千个并发客户端提供服务。现在尝试对服务器上 block 的请求执行相同操作....

标签: c# asynchronous asp.net-core


【解决方案1】:

没那么简单。

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

现在,当您的流量较低时,一切都很好,因此您不会达到线程池中的线程数限制。但是……

为了便于讨论,假设您的请求平均需要 1 秒,并且您的线程池大小 = 100。您将开始遇到第 101 个请求的限制。那个,因为它没有分配给它的线程池,所以必须等待第 100 个请求完成,将线程释放回线程池,然后它才能得到处理。

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

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

  2. 如果您的请求不使用任何 IO 操作,但您强制它们使用异步(有办法做到这一点),那么您实际上要做的就是交换一个线程池线程(最初用于接收请求的线程) ) 为另一个(这将使操作运行)。在这种情况下,您只会产生开销并降低性能。

但是,无论如何,我的感觉与您的问题并不完全相关。 在上述 2 种情况中的任何一种情况下,您的方法都在 2 个单独的请求中运行,并且与 async/await 几乎没有任何关系,而是与独立处理请求的服务器环境有关。

【讨论】:

    猜你喜欢
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 1970-01-01
    • 2018-05-08
    • 2019-12-17
    • 2021-12-16
    • 1970-01-01
    相关资源
    最近更新 更多