0

假设我有一个全天负载很高的队列。队列中的每条消息都需要几秒钟的时间来处理。

如果我有 4 台机器都设置了外部激活器(全部配置为相同的队列/服务),那会工作吗?

如果它确实有效,它会负载平衡(将工作均匀地分布在工作机器上)吗?

4

2 回答 2

3

归根结底,这归结为如何为多个未决WAITFOR (RECEIVE)语句提供服务。假设您有 4 个正在运行的应用程序实例,每个实例都在同一个队列上“侦听”,方法是发出WAITFOR(RECEIVE). 队列中有一条消息可用,问题是:等待中的 WAITFOR(RECEIVE) 中的哪一个会收到该消息

答案让很多人感到惊讶,但这就是它的设计:最近发布的 WAITFOR(RECEIVE) 将收到消息。不是最旧的,不是随机的,而是最新的。换句话说,听众的后进先出顺序。

为什么?这种行为是有意的,其目的是让处理负载所需的侦听器数量尽可能少。您最初有 4 个进程正在侦听。一个人收到消息,处理它,然后它再次发出WAITFOR(RECEIVE),从而开始再次收听更多消息。下一条消息到达时,将确定性地提供给同一进程,因为它是最近发出的 WAITFOR(RECEIVE)。此侦听器将获取消息,对其进行处理,然后再次发出 WAITFOR(RECEIVE)。并且将再次确定性地收到下一条消息。这是它的要点:如果这个单一的监听器可以处理所有传入的流量,那么其他 3 个是冗余的。一段时间后,他们等待的 WAITFOR(RECEIVE) 将超时,这些进程可以安全地离开(退出)。

只有当第一个侦听器正忙于处理另一条消息(即它没有发布新的 WAITFOR(RECEIVE))时,第二个进程才可能收到一条消息(变得可用)。

那么为什么这样好呢?还有另一个难题:了解激活发生的时间。如果单独的处理线程不能再处理传入的流量,则会产生一个新的处理线程(内部或外部),直至配置的 MAX_QUEUE_READERS。

所以你有它,在这两种行为之间,你得到一个自我限制的最佳读者数量(进程,线程):

  • 当流量激增并且阅读器太少时,激活机制将产生一个新的处理线程。这在 5 秒后触发,没有处理线程设法“排空”队列(RECEIVE 返回空行集)
  • 当流量变慢并且激活的侦听器过多时,处理流量所需的最低要求保持活动状态,而剩余的则超时
  • 如果流量在一段时间内完全干涸,所有线程/进程可能会消失(0 等待 WAITFOR(RECEIVE))。当消息到达时,将激活处理线程来处理它。

请记住,由于相关的消息锁定(对话组锁定),队列中可能有消息,但它们都不能被新线程处理(即它们都被锁定)。出于激活/等待目的,这种情况意味着队列是“空的”(没有消息可用于新处理器)。

最后,要让这一切发生,应用程序必须正确运行:

  • 通知时激活一个新线程(内部激活执行此操作,外部激活器也正确执行此操作)
  • 如果语句超时,处理线程应该发出一个 WAITFOR(RECEIVE) 合理的超时并退出(它将返回一个空的结果集,而不是错误)。
  • 必须在激活时发出 RECEIVE。如果您不这样做,队列监视器将进入 NOTIFIED 状态并且不会再次激活任何内容。请参阅了解队列监视器
于 2013-09-05T07:09:35.823 回答
1

要利用内置负载平衡,您需要将服务部署到多个 sql server 实例。我怀疑这不是您的计划,因此您必须想出一个自定义方法,例如有一个内部激活过程,将您到达的消息转发到外部激活过程查看的四个队列之一。

于 2013-09-04T14:53:48.327 回答