【发布时间】:2012-09-23 04:44:13
【问题描述】:
今天,我想在 MVC3 Web 角色的 AsyncController 中模拟等待长时间运行的阻塞进程(5 到 30 秒)。然而,首先,我只是从 1 秒开始,让事情顺利进行。是的,这样做的智慧值得怀疑,因为阻塞操作目前不能在 I/O 完成端口上异步运行到外部服务,但我想看看这种特殊情况下的性能限制是多少。
在我的网络角色中,我部署了 6 个小型实例。唯一的控制器是 AsyncController,它有两个简单的方法来模拟 1000 毫秒的阻塞操作。
MVC3 Web 角色控制器就是这样:
public class MessageController : AsyncController
{
public void ProcessMessageAsync(string id)
{
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew(() => DoSlowWork());
}
public ActionResult ProcessMessageCompleted()
{
return View("Message");
}
private void DoSlowWork()
{
Thread.Sleep(1000);
AsyncManager.OutstandingOperations.Decrement();
}
}
接下来,我从 Amazon EC2 向 Web 角色施加压力。使用 12 台服务器,我缓慢增加负载,接近 550 个请求/秒。任何超出此范围的尝试都会遇到明显的线程饥饿和后续错误。我假设我们达到了 CLR 线程限制,我理解为每个 CPU 100 个线程。计算 AsyncController 的一些开销,对于 1000 毫秒的阻塞操作,每台服务器平均每秒 550/6 = 92 个请求似乎符合这个结论。
这是真的吗?我见过其他人说类似的话,他们在这种类型的负载下每个实例每秒达到 60 到 80 个请求。该系统的负载将主要由运行时间较长的操作组成,因此当 5000 毫秒的任务上线时,每秒 1000 毫秒的 92 个请求将大大减少。
没有通过多个单独的 Web 角色前端路由阻塞 I/O 的请求以将此负载分散到更多内核,有没有办法在 1000 毫秒时获得高于每秒 90 个左右请求的明显限制阻塞时间?我在这里犯了什么明显的错误吗?
【问题讨论】:
-
你是说阻塞过程的持续时间与当前负载无关?因为如果不是,那很可能会比线程数更早成为您的瓶颈。
-
阻塞进程平均为 5 到 30 秒。有些会超过负载均衡器超时值(似乎是 4 分钟)。这将会非常好玩。看起来我需要几百台服务器才能获得任何类型的吞吐量。
-
真正的操作是否真的需要在它运行的全部时间内消耗一个线程?通常,您会尝试“一直向下”异步,这样您就不会在操作期间使用/浪费线程。如果操作在运行时不需要消耗 webapp 的线程,则使用 Task.Delay 将是更好的选择
-
在大多数情况下,实际操作将在 ServiceBus 命名空间中的 TopicClient 或 SubscriptionClient 上使用 BeginReceive()。那应该释放线程。我主要对这些具有阻塞负载的 Azure Web 角色实例的容量感兴趣。当我们有这种负载时,看起来我们可能需要分散到一个“阵列”的网络角色来让更多的核心参与到行动中。在这些情况下,这只是谁被阻止的问题,因为有人会承担这种负载。我们更希望前端 API 有大量的可用容量,而后端的蜜蜂可以等待。
标签: asp.net-mvc iis-7 azure task-parallel-library azure-web-roles