Asynchronous ADO:一路异步到管子下面?

Asynchronous ADO:一路异步到管子下面?,asynchronous,async-await,ado.net,system.io.file,Asynchronous,Async Await,Ado.net,System.io.file,好的,所以“一路异步”是命令。但什么时候会有问题 例如,如果您对资源的访问有限,例如在数据库连接或文件中,您何时停止使用异步方法而支持同步方法 让我们回顾一下异步数据库调用的复杂性: (不放置.ConfigureAwait(false)以确保可读性。) 步骤: 应该是合理无害的,没有什么可担心的 但是现在我们已经在一个可能有限的连接池中获得了一个开放连接。如果在等待步骤2时,其他长时间运行的任务在任务计划程序中位于行的最前面,该怎么办 更糟糕的是,我们正在等待一个开放的连接(很可能是增加了延迟)

好的,所以“一路异步”是命令。但什么时候会有问题

例如,如果您对资源的访问有限,例如在数据库连接或文件中,您何时停止使用异步方法而支持同步方法

让我们回顾一下异步数据库调用的复杂性: (不放置
.ConfigureAwait(false)
以确保可读性。)

步骤:

  • 应该是合理无害的,没有什么可担心的

  • 但是现在我们已经在一个可能有限的连接池中获得了一个开放连接。如果在等待步骤2时,其他长时间运行的任务在任务计划程序中位于行的最前面,该怎么办

  • 更糟糕的是,我们正在等待一个开放的连接(很可能是增加了延迟)
  • 我们的连接保持的时间不是超过了必要的时间吗?这不是一个令人不快的结果吗?使用同步方法来减少总体连接时间,最终使数据驱动的应用程序性能更好,不是更好吗

    当然,我理解异步并不意味着更快,但异步方法提供了获得更大总吞吐量的机会。但正如我所观察到的,当在等待之间安排任务最终会延迟操作,并且由于底层资源的限制,基本上表现为阻塞时,肯定会有奇怪之处

    [注意:这个问题的重点是ADO,但这也适用于文件读写。]


    希望有更深入的见解。谢谢。

    由于数据库连接池在较低协议级别的工作方式,高级打开/关闭命令对性能没有太大影响。一般来说,内部线程调度IO通常不是瓶颈,除非您有一些真正长时间运行的任务—我们说的是CPU密集型或更糟的—内部阻塞。这将很快耗尽你的线程池,事情将开始排队


    我还建议您进行调查,尤其是断路器hystrix的实施。它的工作方式是允许您将代码分组到命令中,并由命令组管理命令执行,命令组基本上是专用的和隔离的线程池。好处是如果你有一个嘈杂的、长时间运行的命令,它只能耗尽自己的命令组线程池,而不会影响应用程序的其余部分。库的这一部分还有许多其他优点,主要是断路器实现,也是我个人最喜欢的折叠器之一。假设一个查询GetObjectById的多个传入调用被分组到一个
    select*where id in(1,2,3)
    查询中,然后结果映射回单独的入站请求。Db call只是一个例子,实际上可以是任何东西。

    由于数据库连接池在较低协议级别的工作方式,高级打开/关闭命令对性能没有太大影响。一般来说,内部线程调度IO通常不是瓶颈,除非您有一些真正长时间运行的任务—我们说的是CPU密集型或更糟的—内部阻塞。这将很快耗尽你的线程池,事情将开始排队


    我还建议您进行调查,尤其是断路器hystrix的实施。它的工作方式是允许您将代码分组到命令中,并由命令组管理命令执行,命令组基本上是专用的和隔离的线程池。好处是如果你有一个嘈杂的、长时间运行的命令,它只能耗尽自己的命令组线程池,而不会影响应用程序的其余部分。库的这一部分还有许多其他优点,主要是断路器实现,也是我个人最喜欢的折叠器之一。假设一个查询GetObjectById的多个传入调用被分组到一个
    select*where id in(1,2,3)
    查询中,然后结果映射回单独的入站请求。DB调用只是一个例子,可以是任何事情。

    这里有一些要考虑的事情:

  • 数据库连接池限制,特别是“最大池大小”,默认为100。数据库连接池具有最大连接数的上限。请务必设置“Max Pool Size=X”,其中X是您希望拥有的最大数据库连接数。这适用于同步或异步

  • 线程池设置。如果加载峰值,线程池将不会快速添加线程。它只会每隔500ms左右添加一个新线程。见和。下面是我的一个项目中繁忙线程数的捕获。由于缺少可用线程来服务请求,负载峰值和请求被延迟。随着新线程的添加,生产线增加记住每个线程的堆栈都需要1MB内存。1000个线程~=1GB的RAM,仅用于线程。

  • 项目的负载特征与线程池相关
  • 您提供的系统类型,我假设您所说的是ASP.NET类型的应用程序/api
  • 吞吐量(请求/秒)与延迟(请求/秒)的要求。异步将增加延迟,但会增加吞吐量
  • 数据库/查询性能与下面的50ms建议有关
  • 文章编辑2018-04-16以下建议适用于基于WinRT UI的应用程序

    避免对非常短的方法使用async/await或使用await 紧循环中的语句(改为异步运行整个循环)。 Microsoft建议使用任何可能需要超过50毫秒的方法 要返回,应该异步运行,因此您可能希望使用 图来确定是否值得使用async/await模式

    另外,请注意讨论线程池和使用异步、同步等问题。

    // Step 1: Ok, no big deal, our connection is closed, let's open it and wait. await connection.OpenAsync(); // Connection is open! Let's do some work. // Step 2: Acquire a reader. using(var reader = await command.ExecuteReaderAsync()) { // Step 3: Start reading results. while(await reader.ReadAsync()) { // get the data. } }
    using (connection)
    {
      await connection.OpenAsync();
      using(var reader = await command.ExecuteReaderAsync())
      {
        while(await reader.ReadAsync())
        {
        }
      }
    }
    
    using (connection)
    {
      connection.Open();
      using(var reader = command.ExecuteReader())
      {
        while(reader.Read())
        {
        }
      }
    }
    
    using (connection)
    {
      await connection.OpenAsync();
      using(var reader = command.ExecuteReader())
      {
        while(reader.Read())
        {
        }
      }
    }