选择一个Web应用程序实例来执行由外部事件触发的任务?

时间:2010-03-04 08:37:49

标签: asp.net sql-server-2005 concurrency iis-6 sqldependency

我有一个在多个IIS6 Web服务器上运行的ASP.NET应用程序,带有SQL Server 2005数据库后端。

我需要:

  1. 监控数据库以完成外部作业事件,然后

  2. 只有一个Web应用程序实例向Web服务提交一些信息

  3. 对于(1),似乎SqlDependency是最好的方法(或者只是普通的旧轮询)。每个Web应用程序实例在启动时都会注册这样的依赖项。 (我不想配置'master'实例,因为该实例的失败意味着任务不会继续,即使其他实例可用。因此我的设计是确保如果有可用的实例工作,然后工作应该继续。)

    对于(2)我一直在考虑在数据库中有一些标志,一旦Web应用程序实例收到(1)中的SqlDependency通知,就会在下一行(大大简化)中尝试更新:

    UPDATE StatusTable SET TaskStatus = 1 WHERE TaskStatus = 0
    
    SELECT @@ROWCOUNT
    

    这个想法是只有一个应用程序实例能够更新TaskStatus,因此只有一个实例会有@@ ROWCOUNT>这将是“当选”将信息提交给Web服务的实例。

    这种方法有哪些不足之处?我还有什么其他选择? (注意:执行此工作的单独服务不是一种选择。)

1 个答案:

答案 0 :(得分:1)

全局“标志”不起作用,请记住,您有多个服务员多个通知,您不希望一个'服务员'拿起所有通知。要可靠地选择“完全一个”任务,请使用带有OUTPUT的UPDATE:

UPDATE TOP(1) StatusTable
   SET Status = 1
OUTPUT DELETED.TaskId
WHERE Status = 0;

这是将用作队列的表中的行出列的推荐的可靠方法,请参阅OUTPUT Clause中的队列段落。

但到现在你应该意识到1)你正在使用表作为队列2)你正在接收来自这些队列的通知; 3)你使用Service Broker来传递这些通知(通过SqlDependency,internally uses Service Broker)。那么为什么不使用普通的Service Broker呢?您需要queueservice并让每个实例在此队列上启动WAITFOR(RECEIVE...)轮询)。感兴趣的工作以SEND为您的服务结束,通知您的工作已完成。确切地说,您的一个实例将接收此通知并继续进行后处理(即,发送Web服务调用)。通过这种方式,您可以删除通知周围的所有“fluf”(SqlDependency,全局标志,用作队列的表),然后您将反对SqlDependency将使用的裸骨基础结构。