【问题标题】:Benchmarking ASP.NET concurrent requests poor results对 ASP.NET 并发请求进行基准测试结果不佳
【发布时间】:2015-12-10 00:44:43
【问题描述】:

我有以下代码,我用 jMeter 进行基准测试,并在我的 localhost 机器上每秒获得大约 3000 个请求(故意缺少 await 以同步运行):

public async Task<HttpResponseMessage> Get()
{
    var resp = new HttpResponseMessage(HttpStatusCode.OK);
    resp.Content = new StringContent(Thread.CurrentThread.ManagedThreadId.ToString(), Encoding.UTF8, "text/plain");
    return resp;
}

问题是,当我像下面这样暂停请求一秒钟时,由于某种原因,每个 w3wp.exe 进程的吞吐量下降到每秒 10 个请求(再次故意缺少 await 以同步运行):

public async Task<HttpResponseMessage> Get()
    {
        Task.Delay(1000).Wait();
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        resp.Content = new StringContent(Thread.CurrentThread.ManagedThreadId.ToString(), Encoding.UTF8, "text/plain");
        return resp;
    }

即使我使用await 也没有区别,每秒 10 个请求也没有任何改善:

public async Task<HttpResponseMessage> Get()
{
    await Task.Delay(1000);
    var resp = new HttpResponseMessage(HttpStatusCode.OK);
    resp.Content = new StringContent(Thread.CurrentThread.ManagedThreadId.ToString(), Encoding.UTF8, "text/plain");
    return resp;
}

我尝试了所有的配置设置,但没有任何改变: `

web.config

  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="65400" />
    </connectionManagement>
  </system.net>

aspnet.config

  <system.web>
    <applicationPool 
        maxConcurrentThreadsPerCPU="100" />
  </system.web>

机器配置

 <processModel
 autoConfig="false"
 memoryLimit="70"
 maxWorkerThreads="100"
 maxIoThreads="100" />

为 x86 和 x64 设置了配置

我有 32 gigs 的内存和 4 个物理内核,Windows 10。

每秒处理 10 个请求时,CPU 的负载不会超过 10%。

上面的代码使用了 WEB API,当然我使用 HTTP Handler 重现了相同的结果。

【问题讨论】:

  • 使用单个通用网络服务器,一个设计良好的 ASP.NET 应用程序将处理大约 300 个请求/秒的真实用户交互。架构不佳的系统开始看到这些零消失。要增加单个 Windows 服务器上的吞吐量,您可以使用“网络花园”来查看。一般来说,您的瓶颈不是您的网络服务器,而是您的共享状态(例如您的数据库)。
  • @ChrisMarisic 我确实使用网络花园
  • 10 req/s 对于 1 秒的请求执行持续时间对于任何技术来说似乎都是很正常的。而且不使用CPU也是正常的(请求只是等待而不消耗任何处理)。你期待什么?

标签: asp.net iis asp.net-web-api


【解决方案1】:

这是一种可能的理解。无论如何都要调查一下。

Task.Delay() 创建一个新任务,其任务是暂停。如果我理解正确,任务通常会被分派到大小有限的 .Net 工作池。 (您可以通过ThreadPool.GetMaxThreads 进行检查)当您尝试放入过多时,代码将在等待线程池有空间时“备份”。

假设您有一个大小为 40 的线程池。一旦您调度了 40 个任务,所有任务都在等待一秒钟,您就可以最大限度地使用线程池。您的瓶颈将是任务,阻塞线程池,而不是产生空间。

通常,执行昂贵 IO 的任务(如数据库查询或文件 IO)会在等待工作完成时产生控制。我想知道 Task.Delay 是否更“粘”。

尝试将 Task.Delay() 替换为 System.Threading.Thread.Sleep(),看看是否有任何改变。

【讨论】:

  • 使用 System.Threading.Thread.Sleep() 将每秒请求数减少到每秒 8 个请求。
【解决方案2】:

我知道对于 Windows 8,最大并发连接数限制为 10,以阻止人们尝试使用消费者操作系统来运行服务器工作负载。 我认为 Windows 10 没有任何不同的原因。

http://blogs.iis.net/owscott/windows-8-iis-8-concurrent-requests-limit

【讨论】:

  • 是的,我也看到了这篇文章,所以安装了 server 2016 来运行测试,但行为根本没有改变。
猜你喜欢
  • 2017-11-28
  • 2018-02-15
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多