如何在处理 nservicebus 消息时使用 ADO 打开多个 sql 连接



我有一个使用 NServiceBus 的消息处理程序,它需要在两个不同的数据库上执行 SQL 代码。 连接字符串具有不同的初始目录,但在其他方面是相同的。

拾取消息时,第一个 sql 连接成功打开,但第二个 sql 连接会导致在 时引发以下异常。称为打开。

分布式事务管理器 (MSDTC( 的网络访问已 禁用。请在安全中启用DTC进行网络访问 使用组件服务管理的 MSDTC 配置 工具。

我们不使用 MSDTC。

下面是失败的代码。 它将在connB.Open((上失败

public void Handle(MyMsgCmd message)
{
using (SqlConnection connA = new SqlConnection(myConnectionStringA))
{
connA.Open();
}
using (SqlConnection connB = new SqlConnection(myConnectionStringB))
{
connB.Open();
}
}

从命令行应用程序或 Web 应用程序运行时,相同的代码工作得很好。 仅当从 NServiceBus 调用异常时,才会引发异常。

这些连接中的每一个在第一次打开或自行打开时都会成功打开,但只要存在第二个连接,第二个连接将始终无法打开,即使已知良好,也会出现相同的异常。

使用 NServiceBus 按顺序打开多个连接是否需要其他配置?

默认情况下,NServiceBus 似乎将每个消息处理程序包装在一个事务中,这会导致对同一消息处理程序内不同数据库连接的查询失败,除非启用了 MSDTC

。我可以使用 BusConfiguration.Transactions(( 禁用它。DoNotWrapHandlersExecutionInATransactionScope((

您可以在 NServiceBus 文档中找到有关事务的更多信息。

这并不完全与 NServiceBus 相关,我们只是提供了连接到传输(如 MSMQ、Azure 服务总线等(、持久化器和你自己的数据库的不同方式。

但是,即使没有 NServiceBus,在连接到两个数据库时,您也需要分布式事务,或者确保事务不会升级到分布式事务。问题是,如果没有分布式事务,当一个事务成功提交时,另一个事务可能会失败。结果是您的两个数据库不再同步或一致。

如果存储了数据库 A 中的订单,并在数据库 B 中跟踪了库存,则可以从库存中扣除 1,但由于交易失败,订单可能永远不会存储。您需要在没有分布式事务的情况下自己补偿这一点。

这并不是说分布式交易总是要走的路。您可能没有使用它们,因为您的 DBA 不喜欢它们。MSDTC 始终将可序列化事务放在具有最重锁的数据上。将它们保持打开状态的时间越长,需要等待的并发运行的事务就越多。您的软件中可能存在巨大的性能问题。

另一方面,创建补偿交易可能非常非常困难。想想数据库A可能会失败,而DatabaseB可能会成功。但是消息会发生什么?它从队列中消失了吗?还是会保留在队列中并再次处理?数据库 B 是否会在重复数据的可能结果下再次成功

幸运的是,您已经在使用 NServiceBus。您可能需要查看发件箱功能,该功能可以帮助解决其中一些问题。

最新更新