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!~

SQL Server Service Broker 简单例子 (转)的更多相关文章

  1. Reusing dialogs with a dialog pool--一个sql server service broker例子

    一个sql server service broker例子 ----------------------------------- USE master GO -------------------- ...

  2. SQL Server Service Broker创建单个数据库会话

    概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...

  3. SQL Server Service Broker创建单个数据库会话(消息队列)

    概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...

  4. The SQL Server Service Broker for the current database is not enabled

    把一个数据恢复至另一个服务器上,出现了一个异常: The SQL Server Service Broker for the current database is not enabled, and ...

  5. 在Windows Server 2008 R2 Server中,连接其他服务器的数据库遇到“未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持。如果希望使用通知,请为此数据库启用 Service Broker ”

    项目代码和数据库部署在不同的Windows Server 2008 R2 Server中,错误日志显示如下: "未启用当前数据库的 SQL Server Service Broker,因此查 ...

  6. SQL Server Service Broker(简称SSB)资料

    SQL server Service Broker (下面简称SSB) 是SQL server 里面比较独特的一个功能.它可帮助开发人员构建异步的松散耦合应用程序.SSB的一些功能和好处包括有: 数据 ...

  7. sql server Service Broker 相关查询

    sql server Service Broker 相关查询 -- 查看传输队列中的消息 --如果尝试从队列中移除时,列将表明哪里出现了问题 select * from sys.transmissio ...

  8. SQL问题:未启用当前数据库的 SQL Server Service Broker

    数据库分离后,附加回到数据库,然后在程序中打开调用数据库的页面,出现如下问题:“未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持.如果希望使用通知,请为此数 ...

  9. 未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持。如果希望使用通知,请为此数据库启用 Service Broker

    昨晚遇到的这个问题,也知道Notifications service依赖底层的Service broker的.本以为只需要执行以下脚本对数据库启用Service broker即可. alter dat ...

随机推荐

  1. 用Redis Desktop Manager连接Redis(CentOS)

    Redis Desktop Manager是Redis图形化管理工具,方便管理人员更方便直观地管理Redis数据. 然而在使用Redis Desktop Manager之前,有几个要素需要注意: 一. ...

  2. Python并发编程-管道

    管道的作用- 两个进程间传递消息 from multiprocessing import Pipe, Process def func(conn1,conn2): conn2.close() #子进程 ...

  3. keil中的memory model

    这两天仿真遇到的怪事真的是一大堆. 还是读写Flash的代码.keil编译OK,但是仿真就是莫名其妙地挂掉出现一些乱七八糟的事情. 后面发现是keil 中的memory model勾选错了,勾选的是l ...

  4. /etc/default/useradd配置文件详解

    /etc/default/useradd文件内容如下: [xf@xuexi ~]$ cat /etc/default/useradd # useradd defaults file GROUP=100 ...

  5. nyoj 311 dp 完全背包

    完全背包 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用.第i种物品的体积是c,价值是w. ...

  6. HDU5904 LCIS 水题

    http://acm.hdu.edu.cn/showproblem.php?pid=5904:// 说是LCIS其实和LCIS没有一点儿关系的水题. 代码 #include<cstdio> ...

  7. bzoj 1776

    收获: 树上直径一定包含深度最深的点. 然后O(nlogn) 暴力. /************************************************************** P ...

  8. Java 请求webServce接口 不带参数

    最近对接了个webService的接口取数据,从网上良莠不齐的代码中找到了个方法, 具体作者已经记不住是谁了,现在把代码贴出来,希望可以帮到大家,代码如下,简单粗暴 public String get ...

  9. 内功心法 -- java.util.LinkedList<E> (7)

    写在前面的话:读书破万卷,编码如有神--------------------------------------------------------------------下文主要对java.util ...

  10. ThinkPHP -- 基础入门

      ThinkPHP文件结构说明: |——ThinkPHP.php    框架入口文件    |——Common            框架公共文件目录    |——Conf              ...