繁体   English   中英

Sql Server Service Broker:如何构建简单队列方案的对话?

[英]Sql Server Service Broker: How to structure Conversations for a simple queue scenario?

我是一个Sql Server Service Broker新手,我正在尝试掌握为一个(看似)简单的用例设置Service Broker的最佳方法:我想创建一个简单的工作队列,其中一个应用程序将工作项丢弃到队列和单独的应用程序从该队列中获取工作项并处理它们。 第一个应用程序不需要从第二个应用程序返回状态消息。 我希望队列存在于单个Sql Server实例中。

最令我困惑的是对话/对话与这种情况的关系。 我知道你只能在对话/对话的上下文中发送/接收消息,但由于这两个应用程序之间没有来回的喋喋不休,我对于何时是创建新会话的正确时间感到迷茫。 两种极端的替代方案似乎是:

  • 每次我排队工作项目,我都会开始一个新的对话。 因此,每个对话最终都只有一条消息。
  • 在部署时,我手动创建一个无限寿命对话。 在将工作项排入队列时,我总是将其作为单个对话的一部分发送。

走这些路线的后果是什么?

此外,在第一种情况下,似乎我需要进行一些END CONVERSATION,以便Sql Server能够在内部清理资源。 什么时候将它们放入正确的地方是否有任何指导? (或者最终依靠对话超时可能会更好?)

您应该从每个工作项开始进行自己的对话。 生产者(发起者)开始一个对话框并发送描述工作项的消息,然后提交。 使用者(目标)接收消息(或被激活),检查有效负载以了解工作项详细信息,执行工作,然后结束对话并提交。 生成的EndDialog消息将被发送回启动器服务队列,并且启动器队列上的激活过程通过在发起方端结束对话来响应它。

这是最简单的部署,启动和运行将确保您有一个良好的基础来构建。 当生产者将工作项排入队列时,不要偷工减料并结束发起人一侧的对话,这是一次又一次的冒险并且有几个缺点

如果您有高性能要求(每秒超过200个请求),那么您将不得不更明确地开始管理对话。 出于性能原因,我有一篇关于重用会话的博客文章。 在接收方面,我建议阅读写作服务经纪人程序

我还有一个博客条目,几乎可以满足您的需求,虽然它不会安排工作项,而是启动自定义过程: 异步过程执行

如果您决定从激活的上下文中使用工作项,从而利用激活的良好自平衡功能,那么您需要了解发生激活的EXECUTE AS上下文

我真的很喜欢Remus的回答,尽管它并没有特别说明为什么你可能更喜欢为每个工作项启动一个单独的对话,而不是将所有工作项放在一个对话中。 与此相关的两个注释:

首先,如果您有多个线程/进程处理工作项,将所有工作项放入单个对话可能会导致并发问题。 服务代理工作进程往往看起来像这样(伪代码):

begin transaction
receive top n work items from queue
process work items
commit transaction

(通过不提交直到工作项成功处理为止,例如,您确保如果您的流程终止,那么它已收到但尚未处理的工作项将不会从队列中删除。)

并发问题将出现,因为服务代理被编程为使得每个RECEIVE命令获取队列中与RECEIVEd共享相同会话(或会话组)的所有消息的独占读锁定。 该锁定一直持续到事务提交为止。 (请参阅对话组锁定 。)因此,如果队列中的所有工作项都在一个对话中,那么当一个工作进程处于“进程工作项”步骤中时,没有其他工作进程可以执行任何工作。

将大量项目放入单个对话的第二个问题是,它会增加您可能丢失或必须在某些错误条件下重新处理的工作项数量。 为了正确描述这一点,我推迟到Remus; 看看他的回收对话 ,特别是“重复使用单个对话框发送所有信息的部分[...]就像将所有鸡蛋放在一个篮子里一样。” 您可能能够从某些错误情况中恢复,但它可能会为您的代码带来更多复杂性。

对于所有工作项使用单个对话可能还有一些争论,但我对它们并不熟悉。

这并不是说正确的解决方案始终是为每个工作项启动单独的对话。 在阅读了Remus的帖子之后,他的建议似乎很合理; 从每个对话开始一个工作项,然后根据需要添加复杂性。 (但在任何情况下,您都不应该将所有消息放在一个对话中。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM