作者:ub皓祉 | 来源:互联网 | 2023-05-17 19:05
这几天在学SQLServer2005中新提供的ServiceBroker,关于servicbroker我能找到的资料有以下一些MSDN里有一篇<<SQLServer200
这几天在学SQL Server 2005 中新提供的Service Broker,关于servic broker我能找到的资料有以下一些
MSDN 里有一篇 <> 推荐
手上那本 胡百敬的 <>
Rickie Lee's blog 分类Sql Server 2005 里也有几篇比较有价值的文章
接着就是微软的 那2个WebCast 视频,
其他的中文资料,在Google,Baidu里找来找去,基本上多是采集 MSDN那篇(搞的我很郁闷)
在看了以上的资料后,我开始动手按上面给出的代码做起来
开始一切多挺顺利的, MSDN那个Hello World示例代码 复制下来就可以运行了,但当时对里面的几行代码比较困或
在Hello World 里建立了两个队列 HelloWorldTargetQueue,HelloWorldInitiatorQueue,以及与他们对应的服务
HelloWorldRequestService,HelloWorldResponseService.当时很困惑为什么 HellowWorldTargetQueue不与HelloWorldResponseService对应,因为Response动作一般由服务端发出(ASP做多了,呵呵),后来发现,在 Service Broker里两端是对等的,并且一个队例可以对应多个服务. 反正一句话可能作者搞错了,但是不影响运行...
这个例子在一个数据库里运行很顺利,但很多时候,我们可能需要在2个不同的数据库里运行,一个做为客户,一个做为服务,当你这么想时,你可能就会像我一样马上去尝试,但麻烦接着就来了,以至于我郁闷了3天,去解决着个问题
这3天里很多时间化在找资料上, 我的环境大至是这样的,在一个SQL 实例里(一台电脑上,一个...什么你不知道SQL实例是什么,那算我没说) 有2个数据库 S与C 现在要求,由C发消息到S数据库的Service Broker Service里(我也不想说的这么麻烦 -_")S的Serveic Broker在收到消息后,启动一个写好的存储过程来处理这些消息..(为什么你一点反映多没?以上这些操作可以是异步的,难道你一点多不觉的激动???,现在不用MSMQ,可以直接在数据库级别实现了!!,晕,还是没反映-_"")
我的代码是这样的:
S 数据库
Create Message Type XMLMessage
Validation = WELL_FORMED_XML
Create Contract XMLContract
(XMLMessage Sent by ANY)
--可以在声明队列时指定处理程序,详细见MSDN帮助(哈哈)
Create Queue ReceivingQueue With Status=ON, Retention=OFF
Create Service ReceivingService On Queue ReceivingQueue
(XMLContract)
C 数据库
Create Message Type XMLMessage
Validation = WELL_FORMED_XML
Create Contract XMLContract
(XMLMessage Sent by ANY)
Create Queue SendingQueue With Status=ON, Retention=OFF
Create Service SendingService On Queue SendingQueue
(XMLContract)
接着我们在C数据库里发送消息
Declare @xml_msg xml
Set @xml_msg='这是消息'
Declare @handle uniqueidentifier
Begin Dialog Conversation @handle
From Service SendingService
To Service 'ReceivingService'
On Contract XMLContract
WITH ENCRYPTION = OFF, LIFETIME = 100;
Send on Conversation @handle
Message Type XMLMessage
(@xml_msg);
End Conversation @handle
好了,点了一次,发送了,没有任何提示
接着在S:数据库里检测一下有没有收到
Select Cast(Message_Body as xml),* From S.dbo.ReceivingQueue
这位同学,你不要急着去试,以上代码我试了几百遍, S.dbo.ReceivingQueure里是没用任何消息!
为什么?因为2个不同的数据库之间发消息需要"路由",(什么路由?天那!)不要紧张,这个路由并不是你没搞清楚的那个路由,这个路由简单的说就是这样的
=========Copy 自Rickie Lee's blog
1. Create a new route to the routing table for the current database (initiator)
For outgoing messages, Service Broker determines routing by checking the routing table in the local database.
For example,
Use [Initiator DatabaseName]
CREATE ROUTE HelloRoute
WITH
SERVICE_NAME = 'SendingService',
BROKER_INSTANCE = 'a727462b-52e7-4405-9eee-d19923729790',
ADDRESS = 'LOCAL' ;
==========================================
很开心吧?问题终于解决了,,呵呵,没有...
正常人多知道[Initiator DatabaseName]指的是发出消息的数据库也就是C数据库,SERVICE_NAME = 'SendingService'中'SendingService'指的是
发出消息数据库里的服务也就是C中的SendingService服务(From Service SendingService 你没看到吗)
但是,很郁闷作者笔误了(虽然他用键盘)
正确的是
在C:数据库下运行
CREATE ROUTE HelloRoute WITH SERVICE_NAME = 'ReceivingService', BROKER_INSTANCE = 'a727462b-52e7-4405-9eee-d19923729790', ADDRESS = 'LOCAL' ;看清楚 是'ReceivingService'不是'SendingService',至于 'a727462b-52e7-4405-9eee-d19923729790'你可以用:SELECT service_broker_guidFROM sys.databasesWHERE database_id = DB_ID('S') --是S哦!得到,另外大家可以看到发消息时有如下句子(直接上面拷贝的你不知道!!)From Service SendingService
To Service 'ReceivingService' --这里用'ReceivingService'其实'ReceivingService'用字符串就是 用来在查询Select * From sys.routes Where Remote_service_name='ReceivingService'中找出对应的Broker_instance(详细信息看MSDN...)好了,这下好了再次发个看看,先去上个WC,洗手,接着祈祷,点了(F5),...成功了!!,哈哈....郁闷还是不行,是那个 CREATE ROUTE HelloRoute WITH SERVICE_NAME = 'SendingService', 作者是对的?这位同学,你怎么一下子动摇了啊?,(呵呵其实我当时,也这么想的)但是,不是这个有问题?还会那里有问题?找找代码!很希望哪个单词拼错了(在面对未知时,人们总是有这样美好而简单--或说小白的希望)但2天下来...哎,您没看见吗,上面就那么几行代码,正常人多不会错的,于是就在网上寻求帮助,发Email,论坛发贴,什么"跪求"啊,"献身"啊,"跳楼"啊,...等字眼多在我发的贴的标题里出现了.....接着3天过去了(打开邮箱一看,...看来老师们,达人们,还有大虾们多很忙...反正没人回),论坛里我发的求救贴,好歹有几个人回了,不过,那几个人多偶本人,回的内容也就是一个字 '顶'.....不搞了,见鬼去吧,以后用到了再说接着就看到,I spent quite a while trying to debug what's going on and I found that the topic in Books Online on "Troubleshooting Service Broker" and, particularly, "Troubleshooting Routing and Message Delivery" is excellent for helping with this上面这些内容是在 Rickie Lee's blog 那片文章下面的一个引用地址里找到的,他说可以在MSDN那个帮助里找到帮助,(废话,帮助,当然是帮助,要不就不叫帮助)带着绝望的心情去看MSDN中 <<路由>>里的<<故障排除>>发现有这么个东西sys.transmission_queue (什么你没找到?再找找)当消息发送后你可以用 Select * From sys.transmission_queue 检查一下.如果查询结果是空,就表明消息很可能(是可能哦)成功发出去了,我运行这个查询后,在结果集中有这么一列 transmission_status,错误信息就显示在这一列 , 你可以在点发送后, 再点(运行) Select * From sys.transmission_queue 不要把这2个动作(上面的发消息,与Select * From sys.transmission_queue 这2个查询)放在一个批处理里...(为什么,为什么老爱问为什么呢??,你自己想想,反正,具体的我说不清楚)我这里 transmission_status列里的消息是:"An exception occurred while enqueueing a message in the target queue. Error: 916, State: 3. The server principal "sa" is not able to access the database "S" under the current security context."==================传说中的分割线=========================== 接着,又是,如此这样,这样如此, google,baidu ,哎,什么搜索引擎(搞个什么多不知道)请原谅我当时确实很郁闷,在google,baidu搜寻了半天....最后去了MSDN的论坛我英文很菜,为什么非要我去鬼子的地方呢,对着词霸找到了下面这么一个贴子 It is indeed part of the SQL 2005 security lockdown. The details are explained in BOL 'Extending database impersonation using EXECUTE AS', http://msdn2.microsoft.com/en-us/library/ms188304.aspx
The easy fix is to make the database A trustworthy: ALTER DATABASE ... SET TRUSTWORTHY ON. If you don't trust the dbo of database a (doesn't seem to be the case, since is 'sa' from your message), then you'd have to use certificate based dialog security.
HTH,
~ Remus
特别地:The easy fix is to make the database A trustworthy: ALTER DATABASE ... SET TRUSTWORTHY ON.
当然,上面还有'Extending database impersonation using EXECUTE AS'
反正管不了那么多了
Alter Database C Set Trustworthy ON
Alter Database C Set Trunstworthy ON
再 Send 一下,也不WC, 洗手了,...如果还不能用就拉到了...
结果可以了, 汗~~~~~~
==================
以上就是这三天捣鼓的一点东西,写出来,希望有用,也给自己当学习笔记
刚开始学,不知道的东西很多,要继续努力了