【问题标题】:Is NServiceBus (AsA_Server) without DTC possible?没有 DTC 的 NServiceBus (AsA_Server) 可能吗?
【发布时间】:2011-07-19 13:46:54
【问题描述】:

我第一次使用 NServiceBus 并且有一个小而简单的应用程序,用户在其中提交表单,然后将表单字段发送到队列,处理程序收集这些数据并使用 linq 将其写入数据库- to-sql。

就 DBA 而言,组件服务中的任何更改都是完全禁止的,因此我现在正在寻找 DTC 的替代方案(在 DB 服务器上未启用),但使用 AsA_Server 以便消息不要被清除。

我尝试在 IConfigureThisEndpoint 之后删除 AsA_Server 并自己指定配置,但这似乎不起作用(控制台出现,页面加载但没有任何反应,它甚至不会在断点处停止。)AsA_Client 确实有效,但是据我了解,这些消息将在启动时被清除,这是我需要避免的。

有什么建议吗?

谢谢,

OMK

编辑:现在已通过使用将数据库调用包装在抑制事务范围内来解决此问题,这允许在没有环境事务登记的情况下完成数据库工作:

using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Suppress)) 
{ 
     // code here 
     sc.Complete(); 
} 

【问题讨论】:

    标签: linq-to-sql nservicebus msdtc


    【解决方案1】:

    当您使用 AsA_Server 时,您指定需要持久队列,并且需要配置事务队列。

    对于事务性发送/接收,MSMQ 要求您将发送、传输、接收和处理作为一个事务的一部分。然而,实际上所有这些阶段都发生在它们自己的交易中。

    例如,当发送者将消息发送到其本地 MSMQ 子系统时,发送事务完成(即使队列地址是远程的,发送者仍将发送到本地队列,该队列充当远程队列的一种代理)。

    当发送方机器上的 MSMQ 子系统成功地将消息传输到接收方机器上的 MSMQ 子系统时,传输事务就完成了。

    即使这可能都发生在一台机器上,我猜你的 Handle() 方法正在写入另一台机器上的数据库。

    这里的问题是,为了让接收操作从事务的角度令人满意地完成,您对数据库的调用必须成功。只有这样,消息才会从您的输入队列中出列。这可以防止消息在处理失败期间丢失的任何机会。

    但是,为了在整个网络中强制执行,您需要让 DTC 来协调分布式事务到数据库。

    底线,如果您想在分布式环境中使用持久队列,那么您将需要使用 MSDTC。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回复并解释了 MSDTC 的必要性 - 非常感谢。看起来我在尝试实现 NServiceBus 时遇到了障碍,因为配置 DB 服务器“不是一种选择”来以更礼貌的方式引用 DBA! :o) 当然,除非企业很乐意与 AsA_Client 合作。除了丢失队列中的任何消息之外,使用 AsA_Client 与使用 AsA_Server 相比,我们还会面临其他问题吗?再次感谢。
    • 如果我是你,我会让你的上级介入。在我看来,不允许数据库服务器上的 MSDTC 支持远程事务有点不合理。您可以在不打开整个程序的情况下启用 DTC(可以保证调用者和服务器之间的相互身份验证)。要回答您的其他问题,使用 AsA_Client 不会再遇到任何问题。
    • 另一个可能的解决方案不是直接调用数据库,而是以某种方式在您的 Handle() 实现中调用一些异步过程。也许是一些“离线”数据写入服务。这将立即返回,从而允许您的接收事务提交。然后其他进程可以以“离线”的方式将数据写掉。
    • 很高兴听到 DBA 有权做出可能丢失业务数据的决定。通常这个决定属于企业而不是技术人员。希望您没有处理任何对您的业务至关重要的数据!
    • 确实,即使抑制事务,您也不应该像休所说的那样丢失消息,因为与数据库交谈的异常应该导致消息队列事务中止。但是,还有另一个潜在的问题,即数据库事务可以完成,但消息队列事务仍然可以中止。例如,考虑在提交数据库事务后断电。在这种情况下,消息队列事务将中止,您将收到两次此消息并执行两次相同的事务。
    【解决方案2】:

    还有一个选择。在您的连接字符串中,您可以添加不参加分布式事务的选项,这将使您的数据库连接在 DTC 中被忽略。

    当然,如果在配置中设置了此项,则 DTC 会忽略应用程序的所有数据库事务,而不仅仅是一个特定的事务。

    例子:

    <add key="DatabaseConnectionString" value="Data Source=SERVERNAME;Initial Catalog=DBNAME;Integrated Security=True;Enlist=False"/>
    

    【讨论】:

    • +1 如果您的端点仅读取数据,例如message enricher,这也是一个很好的选择。
    • 这是一个很好的答案。它解决了我所有的问题。因此,我只能为不支持它的单个数据库禁用 DTC。
    【解决方案3】:

    使用 NServiceBus 4.0,您现在可以执行以下操作,这最终对我有用:

     Configure.Transactions.Advanced(t =>
                    {
                        t.DisableDistributedTransactions();
                        t.DoNotWrapHandlersExecutionInATransactionScope();
                    });
    

    【讨论】:

      【解决方案4】:

      当您使用 As (AsA_Client, AsA_Server) 接口时,配置会在 Init() 之后应用,因此您在那里所做的有关 MsmqTransport 和 UnicastBus 的所有设置都会被覆盖。

      可以在 IHandleProfile 实现中使用 IWantTheConfiguration 覆盖这些设置。您在应用默认角色之后但在总线启动之前获得配置。

      通过这种方式,您可以更改默认配置文件设置并根据您的需要进行调整:停用交易、启用模拟...

      例子:

      public class DeactivateTransactions : IHandleProfile<Lite>, IWantTheEndpointConfig
      {
          private IConfigureThisEndpoint configure;
      
          public IConfigureThisEndpoint Config
          {
              get { return configure; }
              set
              {
                  this.configure = value;
      
                  Configure.Instance.MsmqTransport()
                      .PurgeOnStartup(false)
                      .IsTransactional(false); // Or other changes
              }
          }
      
          public void ProfileActivated()
          {
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-10
        • 2023-03-19
        相关资源
        最近更新 更多