关于如何在 Service Broker 中组织队列的建议

JNK*_*JNK 7 sql-server sql-server-2008-r2 service-broker queue

我有一个服务代理应用程序,目前在两台服务器上有 5 或 6 个队列。

一般工作流程是:

服务器A

  • 用户填充一些表
  • 用户触发存储过程,将消息放入标头队列,指示有工作要做
  • Broker 从这个头队列中读取,并创建大量的消息发送到服务器 B

服务器B

  • 消息全部进入 1 个队列
  • 在这个队列中,消息被检查和解绑,有效载荷被运行,并且响应是从我们与之交互的另一组过程/表中收集的
  • 响应消息被创建并发送回服务器 A

服务器A

  • 响应消息进入一个特殊的队列,用于更新用户填充在顶部的表
  • 结束对话消息从发起者队列中读取并用于更新另一个跟踪标题记录进度的表(即处理的 100 条消息中的 50 条)
  • 当我们检测到头记录已被完全处理时,一条新消息被发送到另一个发送通知电子邮件的队列

我曾建议将其中一些队列合并到服务器 A 上,但我不确定最佳做法是什么。其中两个队列的消息处理量相对较高,而电子邮件队列的速度会非常慢。

我们在管理消息类型方面做得(我认为)做得很好,因此理论上我们可以将它们全部放入一个队列中,并且应用程序仍然可以运行。

是否有关于何时维护单独队列以及何时在这种情况下合并的最佳实践?

Rem*_*anu 8

这是一个没有明确选择的开放性问题。YMMV 所以你必须测试。这是我的意见:

如果您希望能够控制激活任务的数量,那么使用一个队列来处理所有事情是一个不错的选择,因为没有全局 max_queue_readers。除此之外,我没有看到很多优点。有人可能会争辩说,单个激活的 proc 更容易维护,但我认为您应该在创建 SSB 激活的流程时使用某种模板/代码生成,因为通常很多是千篇一律的代码,很少是特定于服务业务逻辑的。

但是,我可以看到单个队列的几个潜在问题,它们都是只有在事情已经变糟时(即在压力/负载下)才会出现的问题:

  • 延迟和处理序列化。只有一个队列可以使 max_queue_readers 达到最大值,并且需要很少处理的消息坐在队列中等待轮到他们被接收。单独的队列允许低延迟服务快速排空它们的队列,而高负载队列以自己(较慢)的速度搅动。
  • 任何服务的消息激增都会影响所有服务。与上面相同,但用于尖峰。大量消息的转储(例如,一些手动“哎呀,我们需要重新处理这个 1MM 项目”)将导致同一队列中的所有其他服务等待,直到峰值耗尽,然后才能访问它们的消息(是由于会话组锁定而稍微复杂一些,但最终处理是 FIFO)。
  • 可以避免进入大排长龙的丑陋土地。如果您的 RAM/IO/CPU/激活代码在 N 条消息上出现大队列问题,则所有服务的一个队列将比每个服务一个队列更快/更频繁地到达 N。

一般来说,我的建议是为每个服务设置一个队列。