【发布时间】:2013-09-03 23:15:23
【问题描述】:
假设我有一个全天负载很高的队列。队列中的每条消息都需要几秒钟的时间来处理。
如果我有 4 台机器都设置了外部激活器(全部配置为相同的队列/服务),那会工作吗?
如果它确实有效,它是否会进行负载平衡(将工作均匀地分布在工作机器上)?
【问题讨论】:
标签: sql-server sql-server-2012 service-broker
假设我有一个全天负载很高的队列。队列中的每条消息都需要几秒钟的时间来处理。
如果我有 4 台机器都设置了外部激活器(全部配置为相同的队列/服务),那会工作吗?
如果它确实有效,它是否会进行负载平衡(将工作均匀地分布在工作机器上)?
【问题讨论】:
标签: sql-server sql-server-2012 service-broker
这最终归结为如何为多个待处理的WAITFOR (RECEIVE) 语句提供服务。假设您有 4 个应用程序实例正在运行,每个实例都在同一个队列上“侦听”,方法是发出 WAITFOR(RECEIVE)。队列中有一条消息可用,问题是:等待中的 WAITFOR(RECEIVE) 中的哪一个会得到消息?
答案让很多人感到惊讶,但这就是设计的原因:最近发布的 WAITFOR(RECEIVE) 将收到消息。不是最旧的,不是随机的,而是最新的。换句话说,听众的后进先出顺序。
为什么?这种行为是有意的,其目的是让处理负载所需的侦听器尽可能少。您最初有 4 个进程正在侦听。一个人收到消息,处理它,然后它再次发出WAITFOR(RECEIVE),从而再次开始收听更多消息。下一条消息到达时,将确定性地提供给同一进程,因为它是最近发出的 WAITFOR(RECEIVE)。此侦听器将获取消息,对其进行处理,然后再次发出 WAITFOR(RECEIVE)。并且将再次确定性地收到下一条消息。以下是它的要点:如果这个单一的侦听器可以处理所有传入的流量,那么其他 3 个是多余的。一段时间后,它们等待的 WAITFOR(RECEIVE) 将超时,这些进程可以安全地离开(退出)。
第二个进程只有在它到达(变得可用)而第一个侦听器正忙于处理另一条消息时才可能收到一条消息(即它没有发布新的 WAITFOR(RECEIVE))。 p>
那么为什么这么好?还有另一个难题:Understanding When Activation Occurs。如果单独的处理线程不能再处理传入的流量,则会产生一个新的处理线程(内部或外部),直至配置的 MAX_QUEUE_READERS。
所以你有它,在这两种行为之间,你会得到一个自我限制的最佳阅读器数量(进程、线程):
请记住,由于相关的消息锁定 (Conversation Group Locks),队列中可能有消息,但它们都不能被新线程处理(即它们都被锁定)。出于激活/等待目的,这种情况意味着队列是“空的”(没有消息可用于新处理器)。
最后,要让这一切发生,应用程序必须正确运行:
【讨论】:
要利用内置负载平衡,您需要将服务部署到多个 sql server 实例。我怀疑这不是您的计划,因此您必须想出一个自定义方法,例如有一个内部激活过程,将您到达的消息转发到外部激活过程查看的四个队列之一。
【讨论】:
waitfor。这样他们就会进行自我负载平衡(当有很多消息时)。我只需要找到一种方法来禁用超时(或在超时发生时重新连接)。