如何以事务方式使用远程MSMQ?
我正在编写Windows服务,该服务从MSMQ中提取消息并将其发布到旧系统(Baan)。如果发布失败或者在发布过程中机器出现故障,我不想丢失该消息。因此,我正在使用MSMQ事务。我失败失败,我承诺成功。
当处理本地队列时,此代码可以很好地工作。但是在生产环境中,我将需要将运行服务的机器与队列本身分开。当我针对远程队列进行测试时,将引发System.Messaging.MessageQueueException:"事务用法无效。"
我已经验证了所讨论的队列是事务性的。
这是从队列接收的代码:
// Begin a transaction. _currentTransaction = new MessageQueueTransaction(); _currentTransaction.Begin(); Message message = queue.Receive(wait ? _queueTimeout : TimeSpan.Zero, _currentTransaction); _logger.Info("Received a message on queue {0}: {1}.", queue.Path, message.Label); WORK_ITEM item = (WORK_ITEM)message.Body; return item;
回答
此后,我已切换到SQL Service Broker。它支持远程事务接收,而MSMQ 3.0不支持。而且,作为一项额外的奖励,它已经使用了我们群集和备份的SQL Server实例。
解决方案
只要MSDTC在两台计算机上都运行,就可以使用TransactionScope。
MessageQueue queue = new MessageQueue("myqueue"); using (TransactionScope tx = new TransactionScope()) { Message message = queue.Receive(MessageQueueTransactionType.Automatic); tx.Complete(); }
我留下评论询问我们使用的MSMQ版本,因为我认为这是造成我们问题的原因。早期版本的MSMQ中未实现事务接收。如果是这种情况,那么此博客文章将说明选择。
此后,我已切换到SQL Service Broker。它支持远程事务接收,而MSMQ 3.0不支持。而且,作为一项额外的奖励,它已经使用了我们群集和备份的SQL Server实例。
为了使用事务作用域,必须先确认已安装MSDTC并激活了远程客户端连接,然后才能使用事务作用域。
安装MSDTC没问题,但是激活远程客户端连接必须导致服务器重新启动(在Windows Server 2003上是这种情况)。
也许这篇文章可以:
如何激活MSDTC和远程客户端连接
避免使用远程MSMQ(否则升级到MSMQ 4.0以支持远程MSMQ事务)。
1)或者,我们可以创建一个Web服务来推送消息
2)创建用于交易目的的本地MSMQ
3)创建一个具有捆绑(batch)号和消息号的小实用程序...一旦该批处理失败,则删除目标处的消息,否则将其作为事务范围