.net - 用于 Windows Server 事务/错误处理的服务总线 1.0

标签 .net wcf msmq msdtc servicebus

我确信我不是第一个这么说的人,但是关于 Windows Server 的 Service Bus 1.0 的细节的文档严重缺乏......我希望一些 MS 内部人士可以帮助澄清一些事情...

  1. 使用队列/主题的服务是否在隐式环境事务中运行?例如,考虑以下代码片段:

    [ServiceBehavior]
    public class MySbService : IDoWork
    {
        [OperationBehavior]
        void DoSomeWork(WorkRequest request)
        {
            DoDatabaseWork();
    
            DoMoreDatabaseWork();
        }
    }
    

    在上面的示例中,如果没有创建显式 TransactionScope,如果 DoMoreDatabaseWork() 抛出异常,DoDatabaseWork() 是否会被提交?换句话说,排队操作是否在 MSDTC 跟踪的环境事务下运行?

  2. 如果引发异常,Service Bus 1.0 队列是否会自动重试(如 MSMQ 那样)?我问这个问题是因为我还没有遇到任何指定重试行为的 netMessagingBinding 设置。此外,当使用 Service Bus Explorer 创建队列时,我看到的最接近的东西是 MaxDeliveryAttempt。来自 MSMQ 背景,我习惯于看到异常消息出现在重试/中毒队列中。在服务总线 1.0 世界中是否存在与此同义的东西?

提前谢谢

更新:

请参阅下面我的回答以了解更多详细信息。我正在修改这个问题以提出以下问题:

是否可以使用契约优先、IIS 托管、带有服务总线 1.0 的 WCF 来“覆盖”客户端在事务中发送到服务总线的情况?如果是这样,怎么办?另外,使用的机制是什么?

最佳答案

我相信我已经找到了我的两个问题的答案......

  1. 对于事务操作,我不相信存在“环境”事务。我通过在数据库操作后简单地抛出异常来证明这一点,并且果然,数据无论如何都会被提交。我想知道是否有声明事务范围的首选方法,即:

    [OperationBehavior(TransactionScopeRequired = true)]
    public void MyServiceOperation(){ ... }
    
    //or using the TransactionScope
    
    public void MyServiceOperation()
    {
        using(var transScope = new TransactionScope(...)){ ... }
    }
    
  2. 对于重试功能,您似乎需要启用 ReceiveContextfollowing this blog :

    [ServiceContract]
    public interface IMyService
    {
        [OperationContract(IsOneWay=true)]
        [ReceiveContextEnabled(ManualControl = true)]
        void MyServiceOperation();
    
    // and in the service implementation:
    
    [OperationBehavior]
    public void MyServiceOperation()
    {
        var incomingProperties = OperationContext.Current.IncomingMessageProperties;
        var property = incomingProperties[BrokeredMessageProperty.Name] as BrokeredMessageProperty;
    
        //Complete the Message
    
        ReceiveContext receiveContext;
        if (ReceiveContext.TryGet(incomingProperties, out receiveContext))
        {
            //Do Something                
    
            receiveContext.Complete(TimeSpan.FromSeconds(10.0d));
        }
    
        else
        {
            throw new InvalidOperationException("...");
        }
    }
    

更新:

深入挖掘后,我发现如果您使用普通的、契约优先、IIS 托管、带有服务总线 1.0 的 WCF,那么 OperationContext` 完成实际上并不是一个选项(不知道为什么,但我希望有人能对此有所启发)

我发现事务行为的唯一合理选择如下:

[OperationBehavior]
public void MyServiceOperation()
{
    using(var transScope = new TransactionScope(...))
    {
        DbWork();
        transScope.Complete();
    }

    Client.SendToServiceBus(); // <-- Cannot be part of transaction, otherwise
                               //     exceptions will be thrown!
}

问题仍然在于,这种模式与 MSMQ 不同,如果将消息发送到服务总线失败,则不允许回滚整个操作。 (当然,除非有人更了解......)

这也意味着您被迫推出自己的重试逻辑以及可能的某种机制来在下一步验证上一步是否已提交。恶心!

据我了解,工作流服务和直接处理代理消息为您提供了一些开箱即用的重试功能。但是,如果您通过 AppFabric 使用 IIS 托管工作流服务,那么 Microsoft 会以某种方式找到如何让事务覆盖发送到服务总线的情况。 (如果有人知道这个机制是什么,请告诉我!)

关于.net - 用于 Windows Server 事务/错误处理的服务总线 1.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15509955/

相关文章:

.net - 如何在没有导出属性的情况下在 MEF 中导出类型? (例如以编程方式)

asp.net - 内部 Azure WCF 服务是否需要安全性

client-server - 使用 MSMQ 的消息传递系统(a la MassTransit)的客户端要求?

tcp - MSMQ 适用于 TCP 还是 UDP?

c# - 测试远程 MessageQueue 是否存在(使用 C#)

c# - 如何在另一个进程正在使用文件时复制文件

c# - Windows Service 需要等待,Thread.Sleep?

c# - 文本框自动完成和默认按钮

wcf - 如何将 T (IEnumerable<T>) 数组转换为 IQueryable<T> 以便使用 LINQ 进行处理?

c# - CRM 创建 CrmConnection 的新实例