【问题标题】:Sql Server Service Broker Conversation GroupsSql Server Service Broker 对话组
【发布时间】:2010-11-21 19:01:03
【问题描述】:

有人可以解释服务代理中的对话组吗?

目前,我正在使用服务代理将消息从一台 SQL 服务器发送到另一台。在发送服务器上,我正在尝试关联消息,以便在接收端对它们进行串行处理。根据文档,对话组似乎非常适合这一点,但在接收服务器上,消息被分配到与我在发送消息时指定的不同的对话组。

我在网上搜索,发现这种行为似乎是有意的 (http://social.msdn.microsoft.com/forums/en-US/sqlservicebroker/thread/baf48074-6804-43ab-844a-cb28a6dce02b/),但后来我对 (http://msdn.microsoft.com/en-us/library/ms178624.aspx) 中的语法的用处感到困惑

WAITFOR( 
  GET CONVERSATION GROUP @conversation_group_id FROM [dbo].[ReceiveQueue]
)

如果会话组没有收到来自发件人的消息,并且使用相同会话组 id 发送的消息在接收方没有相同的会话组 id,那么上面的代码有什么意义?

【问题讨论】:

    标签: sql-server service-broker


    【解决方案1】:

    对话组是用于锁定的本地原语。会话组中的消息没有顺序保证,并且会话组不会跨网络传输。

    消息顺序由对话中的 Service Broker 保证。因此,为了保持处理中相关消息的顺序,请在同一对话中发送它们。

    需要对话组来对一组彼此相关的对话进行分组。 GET CONVERSATION GROUPRECEIVE 动词都保证它们将锁定整个会话组,从而阻止任何其他线程处理相关消息。例如考虑一个旅游网站。它收到一条请求预订假期套餐的消息。结果,它发起与酒店预订服务的对话并发送预订房间的请求,它发起与航空公司预订服务的对话并请求旅行预订,它发起与汽车租赁代理服务的对话并请求预订汽车预订。它创建的这三个新对话都与收到请求的初始对话在同一个组中(应用程序在所有三个对话上都使用了BEGIN DIALOGWITH RELATED_CONVERSATION 子句)。然后它提交并继续处理队列中的消息。这 3 个相关请求的后续响应开始进入,几乎是随机的时间。假设酒店响应首先出现。该消息被应用程序接收,并继续使用酒店的响应更新请求的状态。与此同时,航空公司的响应进来了。如果允许另一个线程来接它,它会尝试更新 same 请求的状态,从而导致阻塞甚至死锁。正在处理酒店响应的线程。处理酒店响应时,线程提交并因此解锁整个会话组,允许任何线程(包括其自身)获取航空公司响应并处理它。

    【讨论】:

    • 谢谢。这是我在网上能找到的最好的解释。也许只有我一个人,但有关此功能的 Microsoft MSDN 文档似乎很含糊。关于如何序列化接收队列上的消息处理有什么建议吗?我正在发送消息,这些消息可能会更新接收端的单个记录。这些消息来自不同的来源,因此确实不能成为同一对话的一部分。我需要确保在接收端相互关联的消息按顺序和串行处理。
    • 目标可以使用 MOVE CONVERSATION 对对话进行分组。然后,它可以将任何“新”对话移动到适当的组中。另一种选择是反转对话启动:“后端”启动对话(并因此控制它们在他身边的分组),“前端”在 target 端点发送对话框。如果后端无法知道前端名称/位置,则可以通过前端发送一条消息来触发“启动”,该消息的含义是“请在此地址订阅我”。正确的解决方案取决于您的方案的具体情况。给我发一封电子邮件。
    • 是的,移动对话方法是我们目前正在研究的。担心的是,由于移动对话锁定了目标对话组,而通过他们的对话组获取消息会锁定关联的对话组,我们可能会陷入死锁情况。我们正处于试图解决这一问题的 POC 中。感谢您的洞察力。
    • 确实 MOVE 有可能出现死锁。感谢您在分析过程中看到这一点。我有点担心您打算使用 GET CONVERSATION GROUP 而不是直接 RECEIVE。 GET 存在的唯一原因是允许模式 GET GROUP/lookup state on group value/RECEIVE WHERE group,但坦率地说,我看不到它的用处,我真的很遗憾 GET CONVERSATION 被允许进入语言。像 RECEIVE NO WHERE/lookup state/process 这样的模式同样易于编码,而且实际上效率更高。
    • @Remus - 这是一个很好的解释。谢谢。我在应用它时遇到了麻烦。我的理解是,通过在发送时指定RELATED_CONVERSATION_GROUP,事务中的WAITFOR (RECEIVE TOP (1) * FROM Q) 将锁定会话组与所有其他事务,直到事务完成。相反,我看到指定的 RELATED_CONVERSATION_GROUP 不是接收到的,也不是 1:1 映射到某个新的接收端 UUID(也就是说,会话组 id 每次接收都会改变,因为你说“会话组不要流过电线”)
    猜你喜欢
    • 2013-09-07
    • 2012-08-01
    • 1970-01-01
    • 2011-02-18
    • 2013-09-21
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 2010-11-18
    相关资源
    最近更新 更多