2009-08-12 61 views
15

我是一个Sql Server服务代理新手,我试着去设置Service Broker(看似)简单用例的最佳方法:我想创建一个简单的工作队列,其中一个应用程序放弃工作项目进入队列,并且单独的应用程序从该队列中提取工作项并对其进行处理。第一个应用程序不需要从第二个应用程序获取状态消息。我希望队列能够存在于单个Sql Server实例中。Sql Server Service Broker:如何构造简单队列场景的对话?

让我最困惑的是对话/对话与这种情况的关系。我知道你只能在对话/对话的上下文中发送/接收消息,但由于两个应用程序之间没有来回的交谈,所以我失去了创建新对话的正确时间。两种极端的选择似乎是:

  • 每次我排队工作项目,我开始一个新的谈话。所以每个对话最终都只有一条消息。
  • 在部署时,我手动创建一个无限生命期对话。当需要排队工作项目时,我总是将它作为单个对话的一部分发送出去。

什么将要去这两种路线的后果是什么?

此外,在第一种情况下,好像我需要做一些结束对话,以便为SQL Server能够在内部清理资源。有什么指导什么时候将这些放在正确的位置? (也可能是潜在更好地依靠对话最终超时?)

+0

您似乎在讨论单个队列,但是... http://stackoverflow.com/questions/14643015/why-do-i-need-two-sql-server-service-broker-queues-for-a-simple-task – cja 2013-02-01 09:19:26

回答

26

你应该对自己的谈话每个工作项目启动。生产者(发起者)开始对话并发送描述工作项目的消息,然后提交。消费者(目标)接收消息(或被激活),检查有效负载以了解工作项目详细信息,执行工作,然后结束对话并提交。得到的EndDialog消息被发送回发起者服务队列,并且发起者队列上的激活过程通过结束发起者侧的对话来响应它。

这是最简单的部署,启动和运行将确保您拥有坚实的基础。从生产者入列工作项目开始,不要偷工减料并结束对话,这是fire-and-forget and has several draw backs

如果你有很高的性能要求(超过每秒200个请求),那么你就必须开始更明确地管理对话。我有一个关于reusing conversations for performance reasons的博客条目。在接收方,我建议阅读Writing Service Broker Procedures

我也有一个博客条目,几乎不需要你做什么,尽管它不安排工作项目,而是启动一个自定义程序:Asynchronous procedure execution

如果您决定从激活的上下文中消耗工作项目,从而利用激活的良好自我平衡功能,那么您需要understand the EXECUTE AS context under which activation occurs

+0

重复使用对话的另一个好处是避免了“Microsoft Internal Work Request 642585”中描述的问题(不公开)。也就是说,您创建和销毁的每个对话都会泄漏TempDB中的少量分配空间,直到您退回实例才会释放这些空间。在高吞吐量的应用程序中,这会浪费TempDB的大小,并迫使您重新启动实例以再次缩小它。 – 2011-10-28 18:28:36

+0

与每条消息使用单独对话的一个问题是,对话可能会在另一端出现乱序。如果在接收端只有一个线程,则甚至会发生这种情况。记住Service Broker只保证会话内的序列。对话的全部原因是在队列的接收端有多个线程时管理排序。如果会话保持顺序以及消息,它将禁止使用多个接收线程。 – 2011-12-09 12:55:54

9

我真的很喜欢Remus的答案,尽管它没有特别的触摸为什么您可能希望开始每个工作项目的单独谈话,而不是将所有工作项目在一个单一的谈话。与此相关的有两点需要注意:

首先,将所有工作项目到一个会话可能会导致并发的问题,如果你有多个线程/进程处理的工作项目。服务代理工作进程往往是这样的(伪代码):

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

(如果不承诺,直到工作项目成功处理,可以确保,例如,如果你的进程死掉了,然后工作项目,已收到但尚未处理的数据不会从队列中丢失。)

并发问题会出现,因为服务代理被编程为使得每个RECEIVE命令都获得队列中共享相同对话的所有消息的独占读锁定(或谈话小组)作为被接受者。该锁一直持续到事务提交。 (见Conversation Group Locks。)所以,如果队列中的所有工作项目都在一个单一的谈话,然后在一个工作进程中的“过程的工作项目”的步骤,没有其他工作进程可以做任何工作。

与投入大量的项目到一个会话的第二个问题是,它增加了你可能会失去,或者在某些错误情况下重新处理工作项目的数量。为了恰当地描述这一点,我遵从Remus;请参阅他的Recycling Conversations,尤其是“重复使用单个对话框发送所有消息[...]”的部分就像将所有鸡蛋放在一个篮子中一样。“您可能能够从这些错误情况中恢复,但它可能会给代码带来更多复杂性。

有要对使用的所有工作项目单个对话可能做出一些更多的争论,但我不熟悉他们。

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

相关问题