Mat*_*rts 12 multithreading azure azure-web-sites kestrel-http-server asp.net-core
我正在使用我们迁移到asp.net core 2.0的asp.net应用程序来解决性能/可伸缩性问题.我们的应用程序托管在azure上作为应用程序服务,并且在任何中等流量下都很容易下降.
令我困惑的一件事是如何处理多个并发请求.从我在这里读到的,Kestrel使用多个事件循环来处理您的请求.但是实际的用户代码是在.net线程池上处理的(就在这里).
所以,作为一个实验 - 我创建了一个新的asp.net核心2.0 MVC应用程序,并添加了一个相当讨厌的动作方法:
[AllowAnonymous]
public ActionResult Wait1()
{
System.Threading.Tasks.Task.Delay(1000).Wait();
return new StatusCodeResult((int)HttpStatusCode.OK);
}
Run Code Online (Sandbox Code Playgroud)
现在,当我把它推到azure时,我希望如果我同时发送100个请求,那么我应该没问题,因为100个请求听起来像是轻微的负载,对吗?等待将发生在线程池线程上,对吧?
所以 - 我这样做并得到一些相当差的结果 - 样本用红色突出显示:
嗯,不出我所料,每个请求约50秒......但是,如果我改变频率,所以请求被分隔开的第二,那么响应时间是罚款 - 刚刚超过1000毫秒回到正如你所期望.看来,如果我同时发出超过30个请求,它开始受到影响,这对我来说似乎有点低.
所以 - 我意识到我讨厌的动作方法会阻塞,但我已经预料到它会阻塞线程池线程,因此能够应对超过我的30.
这是预期的行为 - 如果是这样,只是确保在不使用异步代码的情况下不进行IO绑定工作的情况?
这是预期的行为 - 如果是这样,只是确保在不使用异步代码的情况下不进行IO绑定工作的情况?
根据我的经验,似乎这是预期的行为.我们可以从这个博客得到答案.
现在假设您在IIS上运行ASP.Net应用程序,并且您的Web服务器总共有四个CPU.假设在任何给定的时间点,有100个请求被处理.默认情况下,运行时将创建四个线程,这些线程可用于为前四个请求提供服务.因为在500毫秒过去之前不会添加其他线程,所以其他96个请求必须在队列中等待.经过500毫秒后,将创建一个新线程.
如您所见,为了赶上工作负载,需要100*500ms的时间间隔.
这是使用异步编程的一个很好的理由.使用异步编程,在处理请求时不会阻塞线程,因此几乎可以立即释放四个线程.
我建议你可以使用异步代码来提高性能.
public async Task<ActionResult> Wait1()
{
await Task.Delay(TimeSpan.FromSeconds(15));
return new StatusCodeResult((int)HttpStatusCode.OK);
}
Run Code Online (Sandbox Code Playgroud)
我也找到另一个SO线程,你可以参考它.
| 归档时间: |
|
| 查看次数: |
7083 次 |
| 最近记录: |