SQL Service Broker和内部激活..官方教程中的无限循环是否正确?

时间:2012-08-13 14:52:10

标签: sql-server service-broker

构建使用异步通信的分布式应用程序的基础之一可以表示为不要主动等待任何事件!这样,基于SQL Service Broker的自然解决方案就是使用通过到达队列的消息激活存储过程。

官方Microsoft教程中的Lesson 2: Creating an Internal Activation Procedure显示了如何将存储过程绑定到消息队列。它还建议应该如何实现sp的方式

(我是SQL的新手。但是BEGIN之后不应再有CREATE PROCEDURE... ASEND之前还有一个GO吗?)

我是否理解它?请在代码下面查看我的问题......

CREATE PROCEDURE TargetActivProc
AS
  DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
  DECLARE @RecvReqMsg NVARCHAR(100);
  DECLARE @RecvReqMsgName sysname;

  WHILE (1=1)
  BEGIN

    BEGIN TRANSACTION;

    WAITFOR
    ( RECEIVE TOP(1)
        @RecvReqDlgHandle = conversation_handle,
        @RecvReqMsg = message_body,
        @RecvReqMsgName = message_type_name
      FROM TargetQueueIntAct
    ), TIMEOUT 5000;

    IF (@@ROWCOUNT = 0)
    BEGIN
      ROLLBACK TRANSACTION;
      BREAK;
    END

    IF @RecvReqMsgName =
       N'//AWDB/InternalAct/RequestMessage'
    BEGIN
       DECLARE @ReplyMsg NVARCHAR(100);
       SELECT @ReplyMsg =
       N'<ReplyMsg>Message for Initiator service.</ReplyMsg>';

       SEND ON CONVERSATION @RecvReqDlgHandle
              MESSAGE TYPE 
              [//AWDB/InternalAct/ReplyMessage]
              (@ReplyMsg);
    END
    ELSE IF @RecvReqMsgName =
        N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
    BEGIN
       END CONVERSATION @RecvReqDlgHandle;
    END
    ELSE IF @RecvReqMsgName =
        N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
    BEGIN
       END CONVERSATION @RecvReqDlgHandle;
    END

    COMMIT TRANSACTION;

  END
GO

当消息到达时,调用该过程,并进入“无限”循环。实际上,由于BREAK之后ROLLBACK没有数据到达时(TIMEOUT之后),循环不是无限的。

如果数据到达,则会跳过BREAK。如果预期的消息到达,则回复回复。如果收到...EndDialog...Error消息,则会执行END CONVERSATION。还可以在这里观察其他类型的消息吗?

当一些消息到达(并被处理)时,事务被提交。

但为什么现在循环呢?由于过去通信线路断开,是否有意处理卡在队列中的其他消息?或者因为有更多的消息一次出现而无法如此快速地处理?

当另一条消息排队,并且存储过程仍在运行时会发生什么。是否为其处理分配了另一个工作流程?可以并行启动另一个存储过程吗?如果是,那么为什么循环?

感谢您的帮助,Petr

1 个答案:

答案 0 :(得分:5)

内部激活不像触发器。具体来说,激活的过程为每个到达的消息启动 not 。相反,当有某些事情要处理并且应该在SSB基础设施监视进度时连续地(在循环中)将消息出列时启动该过程,并且如果需要,启动第二个过程来帮助,直到指定的最大值。请参阅Understanding Queue Monitors

在激活的过程中有一个循环并非严格要求,即使没有循环,事情也应该正常。循环应该在非常繁忙的环境中表现更好。另请参见旧的MSDN discussion