SQL Server Service Broker 簡單例子 (轉)


SQL Server Service Broker
服務體系結構

消息類型 — 定義應用程序間交換的消息的名稱。還可以選擇是否驗證消息。
約定 — 指定給定會話中的消息方向和消息類型。
隊列 — 存儲消息。此存儲機制使服務間可以進行異步通信。Service Broker 隊列還有其他優點,比如自動鎖定同一個會話組中的消息。
服務 — 是可尋址的會話端點。Service Broker 消息從一個服務發送到另一個服務。服務指定一個隊列來保存消息,還指定一些約定,約定指明該服務可作為“目標”。約定向服務提供一組定義完善的消息類型。

 

 

處理的先決條件.

USE master;
GO

ALTER DATABASE 目標數據庫
      SET ENABLE_BROKER;
GO

 

-- 如果上面的操作執行后,長時間無反應,有死機的嫌疑,嘗試下面的語句。
ALTER DATABASE 目標數據庫 SET NEW_BROKER WITH ROLLBACK IMMEDIATE;

GO
ALTER DATABASE 目標數據庫 SET ENABLE_BROKER;

GO

 

USE 目標數據庫;
GO

 

 

-------------------- Hello World 的例子 --------------------

-- 創建 SayHelloMessage 消息類型.
-- 該消息類型,不做數據驗證的處理.
CREATE MESSAGE TYPE SayHelloMessage
    VALIDATION = None;
GO

-- 創建 約定 SayHelloContract
-- 定義了,發送/接收方.
-- 都是用這個消息類型.
CREATE CONTRACT SayHelloContract (
  SayHelloMessage SENT BY ANY
);
GO


-- 創建發送/接收隊列
CREATE QUEUE SayHelloSendQueue;
CREATE QUEUE SayHelloReceiveQueue;
GO


-- 創建發起方服務 SayHelloSendService
-- 該服務使用 SayHelloSendQueue 隊列
-- 由於未指定約定名稱,因而其他服務不可將此服務用作目標服務。
CREATE SERVICE SayHelloSendService
  ON QUEUE SayHelloSendQueue;
GO


-- 創建目標服務 SayHelloReceiveService
-- 該服務使用 SayHelloReceiveQueue 隊列
-- 使用 SayHelloContract 約定
CREATE SERVICE SayHelloReceiveService
  ON QUEUE SayHelloReceiveQueue
    ([SayHelloContract]);
GO

 

-- 測試發送.
BEGIN
  -- 定義發送的句柄.
  DECLARE @InitDlgHandle UNIQUEIDENTIFIER;

  -- 定義變量.
  DECLARE @MyMessage NVARCHAR(100);
  -- 設置發送消息的內容.
  SET @MyMessage = N'Hello World!'

  -- 開始事務處理.
  BEGIN TRANSACTION;
  -- 定義消息發送處理.
  BEGIN DIALOG @InitDlgHandle
    FROM SERVICE  -- 定義發送服務.
      SayHelloSendService
    TO SERVICE    -- 定義接收服務.
      N'SayHelloReceiveService'
    ON CONTRACT   -- 定義使用的約定
      SayHelloContract
    WITH  -- 不加密.
      ENCRYPTION = OFF;
  -- 發送消息.
  SEND ON CONVERSATION @InitDlgHandle
    MESSAGE TYPE
      [SayHelloMessage]
        ( @MyMessage );
-- 輸出接收到的消息.
PRINT '我發送了:' + @MyMessage;
  -- 提交事務.
  COMMIT TRANSACTION;
END
GO


-- 測試接收,處理,並反饋.
BEGIN
  -- 接收句柄.
  DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
  -- 接收到的數據.
  DECLARE @RecvReqMsg NVARCHAR(100);
  -- 接收到的數據類型名稱.
  DECLARE @RecvReqMsgName sysname;
  -- 開始事務處理.
  BEGIN TRANSACTION;
  -- 嘗試從 SayHelloReceiveQueue 隊列 接收消息.
  WAITFOR
  ( RECEIVE TOP(1)
      @RecvReqDlgHandle = conversation_handle,
      @RecvReqMsg       = message_body,
      @RecvReqMsgName   = message_type_name
    FROM SayHelloReceiveQueue
  ),  TIMEOUT 1000;

  -- 如果接收到的消息類型名為 SayHelloMessage
  -- 那么進行處理.
  IF @RecvReqMsgName = N'SayHelloMessage'
  BEGIN
    -- 定義准備用於返回的消息.
    DECLARE @ReplyMsg NVARCHAR(100);
    -- 簡單設置.
    SELECT @ReplyMsg = '~' + @RecvReqMsg + '~';
-- 調試輸出.
PRINT '我接收到:' + @RecvReqMsg + "; 我將反饋:" + @ReplyMsg;
    -- 發送反饋消息.
    SEND ON CONVERSATION @RecvReqDlgHandle
      MESSAGE TYPE
        [SayHelloMessage]
          (@ReplyMsg);
    END CONVERSATION @RecvReqDlgHandle;
  END;
  -- 提交事務.
  COMMIT TRANSACTION;
END
GO

 

-- 測試獲取處理結果.
BEGIN
  DECLARE @RecvReplyMsg NVARCHAR(100);
  DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER;
  -- 開始事務處理.
  BEGIN TRANSACTION;
  -- 嘗試從 SayHelloReceiveQueue 隊列 接收消息.
  WAITFOR
  ( RECEIVE TOP(1)
    @RecvReplyDlgHandle = conversation_handle,
    @RecvReplyMsg = message_body
    FROM SayHelloSendQueue
  ), TIMEOUT 1000;
  END CONVERSATION @RecvReplyDlgHandle;
-- 輸出接收到的消息.
PRINT '我接收到反饋:' + @RecvReplyMsg;
  -- 提交事務.
  COMMIT TRANSACTION;
END
GO

 


-------------------- Hello World 內部激活的例子 --------------------

-- 專門用於處理消息的存儲過程.
CREATE PROCEDURE SayHelloQueueProc
AS
BEGIN
  -- 接收句柄.
  DECLARE @RecvReqDlgHandle UNIQUEIDENTIFIER;
  -- 接收到的數據.
  DECLARE @RecvReqMsg NVARCHAR(100);
  -- 接收到的數據類型名稱.
  DECLARE @RecvReqMsgName sysname;
  -- 循環處理.
  WHILE (1=1)
  BEGIN
    -- 開始事務處理.
    BEGIN TRANSACTION;
    -- 嘗試從 SayHelloReceiveQueue 隊列 接收消息.
    WAITFOR
    ( RECEIVE TOP(1)
        @RecvReqDlgHandle = conversation_handle,
        @RecvReqMsg       = message_body,
        @RecvReqMsgName   = message_type_name
      FROM SayHelloReceiveQueue
    ), TIMEOUT 5000;

    -- 判斷有沒有獲取到消息.
    IF (@@ROWCOUNT = 0)
    BEGIN
      -- 如果沒有接收到消息
      -- 回滾事務.
      ROLLBACK TRANSACTION;
      -- 跳出循環.
      BREAK;
    END

    -- 如果接收到的消息類型名為 SayHelloMessage
    -- 那么進行處理.
    IF @RecvReqMsgName = N'SayHelloMessage'
    BEGIN
      -- 定義准備用於返回的消息.
      DECLARE @ReplyMsg NVARCHAR(100);
      -- 簡單設置.
      SELECT @ReplyMsg = '~' + @RecvReqMsg + '~';
-- 調試輸出.
PRINT '我接收到:' + @RecvReqMsg + "; 我將反饋:" + @ReplyMsg;

       -- 發送反饋消息.
       SEND ON CONVERSATION @RecvReqDlgHandle
         MESSAGE TYPE
           [SayHelloMessage]
              (@ReplyMsg);
       END CONVERSATION @RecvReqDlgHandle;
    END;
    -- 提交事務.
    COMMIT TRANSACTION;
  END
END
GO

 

-- 更改目標隊列以指定內部激活
-- 也就是當有消息發送到 SayHelloReceiveQueue 隊列的時候.
-- 自動調用 SayHelloQueueProc 存儲過程 進行處理.
ALTER QUEUE SayHelloReceiveQueue
  WITH ACTIVATION
    ( STATUS = ON,
      PROCEDURE_NAME = SayHelloQueueProc,
      MAX_QUEUE_READERS = 10,
      EXECUTE AS SELF
    );
GO

 

 

 

-- 由於消息已經處於自動處理的方式。
-- 測試發送 並 接收.
BEGIN
  -- 定義發送的句柄.
  DECLARE @InitDlgHandle UNIQUEIDENTIFIER;

  -- 定義變量.
  DECLARE @MyMessage NVARCHAR(100);
  -- 設置發送消息的內容.
  SET @MyMessage = N'Hello World!'

  -- 開始事務處理.
  BEGIN TRANSACTION;
  -- 定義消息發送處理.
  BEGIN DIALOG @InitDlgHandle
    FROM SERVICE  -- 定義發送服務.
      SayHelloSendService
    TO SERVICE    -- 定義接收服務.
      N'SayHelloReceiveService'
    ON CONTRACT   -- 定義使用的約定
      SayHelloContract
    WITH  -- 不加密.
      ENCRYPTION = OFF;
  -- 發送消息.
  SEND ON CONVERSATION @InitDlgHandle
    MESSAGE TYPE
      [SayHelloMessage]
        ( @MyMessage );
-- 輸出接收到的消息.
PRINT '我發送了:' + @MyMessage;
  -- 提交事務.
  COMMIT TRANSACTION;


  -- 等待 5 秒.
  WAITFOR DELAY '00:00:05';


  DECLARE @RecvReplyMsg NVARCHAR(100);
  DECLARE @RecvReplyDlgHandle UNIQUEIDENTIFIER;
  -- 開始事務處理.
  BEGIN TRANSACTION;
  -- 嘗試從 SayHelloReceiveQueue 隊列 接收消息.
  WAITFOR
  ( RECEIVE TOP(1)
    @RecvReplyDlgHandle = conversation_handle,
    @RecvReplyMsg = message_body
    FROM SayHelloSendQueue
  ), TIMEOUT 1000;
  END CONVERSATION @RecvReplyDlgHandle;
-- 輸出接收到的消息.
PRINT '我接收到反饋:' + @RecvReplyMsg;
  -- 提交事務.
  COMMIT TRANSACTION;

END
GO

我發送了:Hello World!

(1 行受影響)
我接收到反饋:~Hello World!~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM