Service Bus 1.0 for Windows Server Transaction / Error Handling

时间:2013-03-19 20:37:44

标签: .net wcf msmq msdtc servicebus

我敢肯定我不是第一个说出来的,但是对于Windows Server的服务总线1.0的细节,严重缺乏文档...我希望一些MS内部人员可以帮助澄清一些事情......

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

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

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

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

  3. 提前谢谢

    更新

    有关详细信息,请参阅下面的答案。我正在修改这个问题以询问以下内容:

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

2 个答案:

答案 0 :(得分:2)

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

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

    [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("...");
        }
    }
    
  3. <强>更新

    深入挖掘之后,我发现如果你使用普通的vanilla,契约优先,IIS托管的WCF和Service Bus 1.0,那么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不同,此模式不允许在将消息发送到服务总线失败时回滚整个操作。 (除非当然有人知道更好......)

    这也意味着您不得不自行滚动自己的重试逻辑,并且可能需要一些机制来在下一步验证上一步是否已提交。 YUCK!

    据我所知,Workflow Services和直接处理代码消息为您提供了一些开箱即用的重试功能。但是如果你通过AppFabric用IIS托管你的工作流服务,那么微软就会想出如何让交易覆盖发送到服务总线。 (如果有人知道那个机制是什么,请告诉我!)

答案 1 :(得分:0)