在多个进程之间拆分工作队列

Posted

技术标签:

【中文标题】在多个进程之间拆分工作队列【英文标题】:Splitting work-queue among multiple processes 【发布时间】:2012-07-17 16:02:37 【问题描述】:

我有一种情况,我认为工作队列和 SqlDependency 非常适合,但我无法将它们拼凑在一起。

假设我有 1000 个实体,每个实体必须以不同的时间间隔(即 15、30 或 45 分钟)进行“处理”。我想在多个进程之间拆分工作,而不必每分钟轮询 SQL Server 以寻找更多工作。我已经阅读了很多与 SqlDependency / Query 通知相关的文章,但不知道如何对工作进行排队以及如何将每个进程限制为一组工作项。

我编写了一个如下所示的 SqlDependency 查询:

select f1, f2, etc from dbo.entity where LastRunDt < datediff(minute, 15, @dt)

查询运行时有 0 个结果,但是当 15 分钟过去后会导致此记录集发生更改(其中有更多项目)时,不会触发通知。我猜它不会以这种方式工作,所以我一直在思考如何让工作项排队。

另外.. 当我将 2 个进程附加到同一个工作队列时,每个进程都会收到通知(当我运行 select * from dbo.entity SqlDependency 查询并更改记录时),但它们都收到相同的工作项。我需要在可用进程之间划分工作项,但不知道有多少个侦听器,可能是 2 个或 12 个,具体取决于哪些服务器在线以及哪些服务器离线进行维护。

客户端将使用 C# 编写。

非常感谢任何已知的模式、想法或方向。

【问题讨论】:

【参考方案1】:

您不需要在这里涉及查询通知。直接使用服务代理。

让您的 C# 应用程序发出 WAITFOR(RECEIVE ...) 语句以获取工作任务。当工作可用时,使用SEND 将消息排入队列。要安排将来的工作,请使用BEGIN CONVERSATION TIMER

此外,Service Broker 可以帮助您实际激活您的 C# 代码,无论是作为内部托管存储过程(参见 Service Broker Activation)还是作为外部独立应用程序(参见 Service Broker External Activator)。

【讨论】:

BEGIN CONVERSATION TIMER 可能是我正在寻找的。我正在考虑创建一个 WHILE() 循环,其中包含 WAITFOR(),但我知道有更好的方法。谢谢。 我确实决定使用 BEGIN CONVERSATION TIMER,但我还有另一种情况,我正在寻找答案。我想听听你的意见 - 请看这个question【参考方案2】:

听起来您需要某种消息队列。有一些常见的中间件包,比如 NServiceBus。

您还可以使用 ServiceBroker,它以事务性和快速的方式与 SQL Server 完美集成。

【讨论】:

谢谢...我对 NServiceBus 有很多用途,但在这种情况下没有。我认为 Service Broker 是要走的路。

以上是关于在多个进程之间拆分工作队列的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ指南之二:工作队列(Work Queues)

多个工作进程调用 HttpReceiveHttpRequest

celery django 守护进程上的多个工作人员和多个队列

RabbmitMQ-工作队列及相关概念

嵌套GNU并行处理多个大文件并将每个文件数据拆分为队列

Laravel Artisan CLI 安全地停止守护进程队列工作者