【问题标题】:Sql server 2008 service broker millions of queuesSql server 2008 服务代理数百万个队列
【发布时间】:2010-11-08 11:15:27
【问题描述】:

我正在为我们的应用程序中的新功能制作线框。其中一个要求是每个用户都有一个要处理的事情列表。

我计划使用 SQL Server 2008 服务代理向用户发送待办事项通知。

但由于代理队列的工作方式,我无法将消息隔离到单个队列中的用户。我只能在检索到消息后才能看到。但是,我只希望它为调用它的用户检索消息。

因此,如果我想使用代理服务,我需要为每个用户设置一个单独的队列。

然后我最终会在代理服务中拥有数百万个队列。

我是否缺少代理服务的任何功能,可以让我拥有一个队列但使用过滤器检索消息?

SQL Server 2008 代理服务可以处理数百万个队列吗?这样做可以吗?

【问题讨论】:

    标签: sql-server


    【解决方案1】:

    消息传递应用程序通常是事件驱动的,即。当消息到达时,它会激活处理消息的处理过程。 Service Broker 通过附加到队列的激活机制来实现这一点。在这种哲学中,不需要过滤消息,因为处理总是处理队列中的“下一条消息”,并且理想情况下,队列总是空的。因此,RECEIVE 动词不提供任何过滤器。 RECEIVE 的 WHERE 子句仅限于对话和对话组,这是帮助应用程序利用 conversation group locking 概念的一种手段,而不是过滤我们的某些消息。

    虽然队列只不过是伪装成一个花哨名称的普通(内部)表,但它们带有一些包袱,这意味着拥有数百万是一个坏主意:

    • 每个队列必须至少有一个与之关联的服务。服务在运行时成本上更重一些,因为它们与消息路由相关联,因此它们消耗启动时间(扫描数据库并创建 tempdb 隐藏实例路由表)、tempdb 空间(所述路由表)和运行时内存(与路由相关的缓存内存结构)。它们还会导致一些 CPU 开销(供路由算法在数百万个候选者之间做出决定)。
    • 如果激活与队列相关联,队列可能会“自行”变得更重。每个队列都有一个运行时对象,队列监视器,它将消耗内存和 CPU,请参阅http://rusanu.com/2008/08/03/understanding-queue-monitors
    • 您将需要至少一个对话才能到达队列,并且实时、活跃的对话可能会产生一些开销。
    • 队列对象与RECEIVE 动词相关联,更重要的是,与WAITFOR(RECEIVE) 相关联。 WAITFOR 会阻塞服务器上的工作线程,并且在您在每个队列上放置 WAITFOR 之前很久,您就会用完 sp_configure 'max worker threads'

    从配置/监控需求的角度来看,队列/服务也比普通表更“活跃”。当我这样说时,我想到了两个问题:poison message detection 可以触发和禁用您的队列,您将很难关注一百万个队列(它可以而且应该是自动化的,但仍然如此)。第二个问题是,如果由于某种原因,消息通过transmission queue 延迟,则可能发生的问题:当传输恢复时,唤醒数百万个对话将表现得非常糟糕(里程可能会有所不同,很大程度上取决于 SQL 版本/SP 级别你是因为一些问题在 SQL 2K5 SP3 之后得到了修复)。

    Service Broker 的设计主要考虑了分布式应用程序的问题(即解决 DCM/COM+、Corba、Remoting 等未解决的问题)。但它是否经常在本地部署,完全包含在单个 SQL 服务器实例甚至数据库中,以利用排队行为和激活机制。如果您查看 SSB 的唯一原因是利用队列,那么我想说的是使用 SSB 队列与构建您自己的用户表支持队列之间的比例为 50/50,如果您倾向于构建自己的队列拥有专业知识(即,您知道如何解决用户表支持的队列带来的许多死锁问题)。如果您还使用 Activation,那么 SSB 更具吸引力,如果您实际上是在进行远程消息传递,那么显然是最佳选择。

    在你的情况下,因为我希望我清楚地说明为什么拥有数百万个队列是一个坏主意。您的消息来自哪里(本地与远程),您为什么要考虑从 Service Broker 开始?在不知道所有细节的情况下,我会说最好的选择是拥有一个队列,这是一个激活的过程,它在所有消息到达时对其进行处理,并将每个用户的相关信息存放在一个普通表中,该表可以通过以下方式正确过滤每个用户都有自己的数据。

    披露:我是Service Broker team and maintain the SSB blog的前成员

    【讨论】:

    • 您将消息转发给其他公司(比如 1000+)的情况如何?理想情况下,由于 A 公司的通信问题,您不希望 A 公司的消息阻止发送给 B 公司的消息?我假设解决方案是在毒消息处理中而不是拥有多个队列?我们遇到的问题是,我们需要通过特定的 Web 服务接口与这些公司集成,因此我们不能使用服务代理将消息转发到公司队列(它们托管)或类似的东西。
    • @spooner:实际上Service Broker内置了转发,整个Service Broker消息栈都是为了公平而设计的,一条消息不仅不能阻塞其他消息,即使是大消息也会与较短的消息交错发送从其他会话。毒药消息处理和队列是关于应用程序而不是基础设施。是用户代码,应用程序,无法处理消息吗?根据定义,这始终是代码中的错误。
    • @spooner:见msdn.microsoft.com/en-us/library/ms166098.aspx了解内置SSB转发
    【解决方案2】:

    有一种方法可以为同一队列上的多个侦听器设置待办事项队列。它需要一个辅助表来跟踪服务代理会话,并利用 RECEIVE 子句中的过滤能力有限这一事实 - 按会话句柄或会话组。

    创建表Listener(ListenerCode varchar(10)主键,ConversationGroup唯一标识符默认newid())

    此表为每个侦听器都有一行。侦听器代码或其他键是每个侦听器的 ID/代码。当您需要向听众发送消息时,您可以查找对话组并在该对话组上发送。这是在 BEGIN DIALOG ... RELATED_CONVERSATION_GROUP= ....

    中指定的

    ConversationGroup 只是一个可以放在对话上的标签,它们没有参考表。 (见http://msdn.microsoft.com/en-us/library/ms166131.aspx。)

    听众查找他们的对话句柄并在该对话组上接收。如果他们不听,他们的消息就会排队。

    一旦使用,消息就会从数据库中消失。如果这是要为用户处理的事情的列表,您可能需要一个持久列表;所以我可能会创建一个任务表,队列中的消息只是对任务表的引用——队列只是新项目的通知,而不是商店本身。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 2011-09-06
      相关资源
      最近更新 更多