我们正在开发一个应用程序,它将使用服务代理将消息从一个数据库传输到另一个数据库。 SourceDB被一个现有的应用程序使用,我们从中抽取一些数据。 TargetDB仅由该应用程序使用并处理/分发我们需要的数据。我们只使用一种类型的合同,两个数据库都在同一台服务器上。
我们已经在两者以及各自的发起者和目标队列/服务上设置了相同的消息类型和合同。在两个数据库上:
ENABLE_BROKER
已设置TRUSTWORTHY
已设置- 拥有独一无二的
service_broker_guid
sa
作为数据库所有者,所有 SSB 授权语句都是ordbo
,OWNER
视情况而定。
但是,当我们从 SourceDB 发送消息时:
BEGIN DIALOG CONVERSATION @dialogHandle
FROM SERVICE [//Service/Initiator]
TO SERVICE N'//Service/Target'
ON CONTRACT [//Contract/Notification]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @dialogHandle
MESSAGE TYPE [//Message/Notification] (@RequestMsg);
...消息在那里找不到。进一步调查显示以下内容:
- 发起者队列为空
- 目标队列为空(注意:不是需要的问题
RECEIVE
) - 传输队列为空
- 无论是在 SQL Server 日志中,还是在创建消息的存储过程中的 CATCH 错误处理中,都没有记录错误
- 如果启用激活,SourceDB 中的启动器队列条目
sys.dm_broker_queue_monitors
将设置为 NOTIFIED - SourceDB 的状态
sys.conversation_endpoints
有一个新条目CONVERSING
sys.dm_broker_queue_monitors
如果启用激活,TargetDB 中的目标队列条目将保持为 INACTIVE- TargetDB
sys.conversation_endpoints
有一个新条目处于CONVERSING
状态,与 SourceDB 的条目具有相同的 conversation_id 和不同的 conversation_handle
虽然测试数据库是 SQL 2005(应用程序必须支持 2005),但我从我的开发机器的 2008 安装中运行了 ssbdiagnose 实用程序来诊断问题:
ssbdiagnose -S testserver -d SourceDB CONFIGURATION FROM SERVICE //Service/Initiator TO SERVICE //Service/Target ON CONTRACT //Contract/Notification
这产生了以下内容:
D 29912 dbtestsvr SourceDB Service //Service/Target was not found
D 29975 dbtestsvr SourceDB User dbo does not have SEND permission on service //Service/Target
这是令人困惑的,因为dbo
不应拒绝任何许可,并且//Service/Target
确实存在,尽管在不同的数据库中。但是我的同事运行了 Profiler 跟踪,显示正在执行的命令正在//Service/Target
SourceDB 上查找。服务经纪人似乎不知何故感到困惑。添加显式路由,除了理论上是不必要的外,并不会改变这种情况。
我在我们的测试服务器上运行了一组几乎相同的教程命令,一切正常,所以它可能是特定于 db 的。
我们的设置在两天前工作,所以我们可能正在寻找一些可能已经更改但没有运气的设置。