没有 DTC 的 NServiceBus (AsA_Server) 是否可行?
我是第一次使用 NServiceBus,有一个小型、简单的应用程序,用户提交表单,然后将表单字段发送到队列,处理程序收集这些数据并使用 linq-to-sql 将其写入数据库。
就 DBA 而言,组件服务中的任何更改都是完全禁止的,因此我现在正在寻找 DTC 的替代方案(在数据库服务器上未启用),但使用 AsA_Server 以便消息不会被获取净化了。
我尝试在 IConfigureThisEndpoint 之后删除 AsA_Server 并自己指定配置,但这似乎不起作用(控制台出现,页面加载但没有任何反应,它甚至不会在断点处停止。)AsA_Client 确实有效,但据我了解它的消息将在启动时被清除,这是我需要避免的。
有什么建议吗?
谢谢,
OMK
编辑:现在已经通过使用将对数据库的调用包装在抑制事务范围中来解决这个问题,这允许数据库工作在没有环境事务参与的情况下完成:
using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Suppress))
{
// code here
sc.Complete();
}
I am using NServiceBus for the first time and have a small, simple application where a user submits a form, the form fields are then sent to the queue, and the handler collects this data and writes it to the database using linq-to-sql.
Any changes within Component Services is a complete no-no as far as the DBA is concerned, so I'm now looking for an alternative to DTC (which is not enabled on the DB server), but using AsA_Server so that messages do not get purged.
I have tried removing AsA_Server after IConfigureThisEndpoint and specifying the configuration myself, but this doesn't seem to work (the console appears, page loads but nothing happens, it doesn't even stop at breakpoints.) AsA_Client does work, but as I understand it the messages will be purged at startup which I need to avoid.
Any suggestions?
Thanks,
OMK
EDIT: This has now been resolved by using wrapping the call to the database in a suppress transaction scope, which allows the database work to be done with no ambient transaction to enlist in:
using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Suppress))
{
// code here
sc.Complete();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当您使用 AsA_Server 时,您指定需要持久队列,并且需要配置事务队列。
对于事务性发送/接收,MSMQ 要求您将发送、传输、接收和处理作为一个事务的一部分。然而,实际上所有这些阶段都发生在它们自己的交易中。
例如,当发送方将消息发送到其本地 MSMQ 子系统时,发送事务就完成了(即使队列地址是远程的,发送方仍然发送到本地队列,该队列充当远程队列的一种代理)。
当发送方计算机上的 MSMQ 子系统成功地将消息传输到接收方计算机上的 MSMQ 子系统时,传输事务就完成了。
尽管这可能全部发生在一台机器上,但我猜测您的 Handle() 方法正在写入另一台机器上的数据库。
这里的问题是,从事务角度来看,为了使接收操作圆满完成,对数据库的调用必须成功。只有这样,消息才会从输入队列中出队。这可以防止在处理失败期间消息丢失的任何可能性。
但是,为了在整个网络中强制执行此操作,您需要使用 DTC 来协调与数据库的分布式事务。
最重要的是,如果您希望在分布式环境中获得持久队列,那么您将需要使用 MSDTC。
希望这有帮助。
When you use AsA_Server, you are specifying you want durable queues and you will need to configure transactional queues.
With a transactional send/receive MSMQ requires you to send, transmit, receive, and process as part of one transaction. However, actually all these stages take place in their own transactions.
For example, the send transaction is complete when the sender sends a message onto their local MSMQ subsystem (even if the queue address is remote, the sender still sends to a local queue which acts as a kind of proxy to the remote queue).
The transmit transaction is complete when the MSMQ subsystem on the senders machine successfully transmits the message to the MSMQ subsystem on the receivers machine.
Even though this may all happen on one machine, I am guessing that your Handle() method is writing to a database on a different machine.
The problem here is that for the receive operation to complete satisfactorily from a transaction perspective, your call to the database must be successful. Only then will the message be de-queued from your input queue. This prevents any chance that the message is lost during processing failure.
However, in order to enforce that across the network you need to involve DTC to coordinate the distributed transaction to the database.
Bottom line, if you want durable queues in a distributed environment then you will need to use MSDTC.
Hope this helps.
还有一个替代方案。在连接字符串中,您可以添加不加入分布式事务的选项,这将使您的数据库连接在 DTC 中被忽略。
当然,如果在配置中进行了设置,则 DTC 将忽略应用程序的所有数据库事务,而不仅仅是特定的事务。
例子:
There is an alternative. In your connection string you can add the option to not enlist in a distributed transaction and this will have your DB connection ignored in the DTC.
Of course, if this is set in the config then all database transactions for the application are ignored by the DTC rather than just a specific one.
Example:
使用 NServiceBus 4.0,您现在可以执行以下操作,这最终对我有用:
With NServiceBus 4.0 you can now do the following, which finally worked for me:
当您使用 As(AsA_Client、AsA_Server)接口时,配置会在 Init() 之后应用,因此您在此处所做的有关 MsmqTransport 和 UnicastBus 的所有设置都会被覆盖。
可以在 IHandleProfile 实现中使用 IWantTheConfiguration 覆盖这些设置。您可以在应用默认角色之后但在总线启动之前获取配置。
通过这种方式,您可以更改默认配置文件设置并根据您的需求进行定制:停用交易、启用模拟...
示例:
When you use the As (AsA_Client, AsA_Server) interfaces, the configuration is applied after Init() so all the settings that you make there regarding MsmqTransport and UnicastBus are overriden.
It's possible to override those settings using IWantTheConfiguration in a IHandleProfile implementation. You get the Configuration after the default roles are applied but before the bus is started.
This way you can change the default profile settings and tailor them to your needs: deactivate transactions, enable impersonation...
Example: