我问了一个关于在 SQL Service Broker 设置中实现对话组的问题,该设置有几个用户服务与服务器服务通信(处理要发送到外部 Web 服务的 xml 数据请求)。但是由于会话组不保证处理中的顺序,您是否认为对所有进入同一目标队列的请求使用相同的会话句柄有什么问题(保证无论来源如何发送它们的顺序) ?
背景: 您将如何为 Service Broker 队列的多个用户实现对话组/锁定?
正如Rusanu在回答中提到的那样,
并且不要忘记,在 SSB 中保证顺序的唯一构造是对话。因此,如果用户必须在会话 1 上发送对 A 的出价,然后在会话 2 上发送对 B 的出价,则不能保证在处理 B 的出价后会处理对 A 的出价。唯一的保证是,如果用户 1 为 A 发送了两次出价,它们将按照发送的顺序进行处理。
此外,如果两个不同的用户为产品 A 发送投标,则无法保证这些投标的处理顺序。但是,如果产品 A 的投标最终出现在相同的 CG 上,则可以保证只有一个“处理器线程”会同时看到用户 1 的投标和用户 2 的投标,但要小心,因为不能保证投标在 RECEIVE 结果集中按照它们被接收的顺序呈现。RECEIVE 仅保证:
* all messages in the result set are from the same CG * the messages belonging to a conversation are in order
但结果中的对话顺序基本上是随机的(由对话句柄顺序驱动,一个 GUID)。
就像在真正的拍卖中一样,我实际上希望队列项目按照它们到达队列的顺序进行处理,用户 A、用户 B 和用户 C 发送相同产品的“投标”。我正在考虑通过对同一产品上的所有对话使用相同的对话句柄来实现整个事情。
到目前为止我想我会尝试什么:
该机制将是服务器应用程序将 N 个对话的对话启动器(初始化)发送到 User_0(其中 N 是我们将拥有的“多路复用对话通道”的数量)——我们将对话句柄存储在类似这样的表中:
CREATE TABLE ConversationChannelStatus
(ConversationChannel_pk numeric Primary Key, ConversationHandle UNIQUEIDENTIFIER)
USER_A 在发送“投标”时,将使用保存在 ConversationChannelStatus 表中的会话句柄从 User_A 服务向目标服务发送消息(由简单的数字主键“ConversationChannels”索引)。
将会话句柄存储在表中是否有问题,然后让多个启动器服务在向目标队列发送消息时继续使用相同的会话句柄?
谢谢你。
更新:抱歉对这些词感到困惑,对话 ID,对话句柄。绝对不能使用相同的会话句柄,因为它对于发起者和目标是不同的。我想我指的是尝试使用来自多个发起者的相同对话 ID 到同一个目标,以尝试维护来自多个服务的队列处理消息的顺序。
更新 2:仍在努力,但我想解决方案将是这样的,涉及对话句柄和对话组 ID。
- 首先初始化 N 个对话与用户 0,并将对话组 ID 和对话句柄都存储在频道设置表中。
- 当 UserA、UserB、UserC 服务想要加入时,服务器应用程序实际上会使用我们之前存储在频道设置表中的对话句柄与每个用户服务发起 N 次对话。
- 然后,用户服务(该消息的目标)将接收该消息并使用频道设置表中的会话组 ID 进行回复,仅当用户服务有“出价”要发送时。因此为用户服务提供了一种简单的方法来知道要使用哪个相关的会话组 ID,同时在服务器上保持所需的会话顺序APP服务队列处理来自用户 A、B、C 的消息(因为它正在回复由serverapp 服务)。我希望它有效!
竞争将是最大的问题。会话保证顺序,但为了提供这种保证,SEND 动词必须锁定使用的会话句柄,直到事务结束(或者如果没有使用显式事务,则在语句期间)。实际上,这意味着在任何时候只有一个交易可以发送对产品 A 的出价。这是否可以接受完全取决于您的业务需求。
术语:对话有两个端点,发起者和目标。每个对话都有一个唯一的 ID,即
conversation_id
(a guid),它在两个端点上具有相同的值(即,它与消息一起在线路上传播)。每个端点都有自己的句柄,即conversation_handle
与 SSB 动词一起使用的(又是一个 guid)。句柄仅是本地的,并且永远不会与消息一起传播。所以你在更新中做对了;)我认为您在更新 2 中描述的内容还可以,但魔鬼总是在细节中。我建议你开始尝试原型代码并交换真实的消息,一旦你看到它工作,你会得到更好的感觉。