1

我们有一个 ASP MVC 3.0 应用程序,它使用实体框架(全部在 Azure 上)从数据库中读取数据。我们有几个长时间运行的查询(已完成优化),我们希望确保该解决方案具有可扩展性并防止线程饥饿。

我们查看了异步控制器并使用 I/O 完成端口来运行查询(使用 BeginExecute 而不是通常的 EF)。然而,异步很难调试并且增加了代码的复杂性。

建议的解决方案如下:

  1. Web 服务器(Web 角色)获取涉及长时间运行查询的请求(例如客户细分)

  2. 它将请求信息连同相关参数一起输入到表中并返回,从而允许线程处理其他请求。

  3. 我们在 db 中设置了一个标志,使 UI 能够在页面刷新完成时声明查询正在进行中。

  4. 工作人员角色不断查询此表,并在找到此条目后立即处理长时间运行的查询(客户细分)并使用结果更新原始客户表。

在这种情况下,不需要立即将状态返回给用户。用户可以在几分钟内回来查看他们的请求是否已得到处理。而不是我们计划使用 Azure 队列的表(但我猜 Azure 队列无法通知工作人员角色,因此 db 表就可以了)。这是一个可行的解决方案。这样做有什么陷阱吗?

4

2 回答 2

1

虽然 Windows Azure 存储队列不会在处理完消息后给您通知,但您可以自己实现它(可能使用 Windows Azure 存储表)。队列的优点:它们处理并发和失败的尝试。

例如:如果您有 2 个工作程序实例处理来自同一个队列的消息,则每次读取队列消息时,该消息都会在您指定的时间内在队列中不可见。虽然不可见,但只有读取消息的工作实例拥有它。如果该实例完成处理,它可以删除队列消息(并更新您的通知表)。如果失败(可能是由于角色实例崩溃),则消息会在不可见超时到期后重新出现在队列中。更进一步:假设这只是一条导致您的代码每次都崩溃的错误消息。您可以在处理消息之前检查出队计数。如果它大于 2,只需将消息存储在死信表中并手动检查它。

对队列的一个警告:队列消息需要是幂等操作(也就是说,它们至少可以处理一次,并且每次的结果应该具有完全相同的副作用)。

如果您使用表而不是队列,则需要处理缩放(处理表的多个线程或角色实例)和死信处理。

于 2012-07-03T12:05:48.910 回答
1

这取决于。如果您的工作角色除了将繁重的工作委派给 SQL 数据库之外什么都不做,这似乎是在浪费资源和金钱。使用带有异步请求的 Web 角色可以降低成本。如果需要在worker角色本身做繁重的工作,那么这是一个很好的方法。

您还可以使用 AJAX 或 Web 套接字。启动数据库查询,并立即返回响应。客户端可以轮询 Web 角色以查看查询是否已完成(如果您使用 HTTP),或者 Web 角色可以直接通知客户端(如果您使用 Web 套接字)。

于 2012-07-04T14:12:51.413 回答