Service Bus 1.0 for Windows Server Transaction/Error Handling

纵然是瞬间 提交于 2019-12-06 11:43:42

问题


I'm sure I'm not the first to say it, but there's a severe lack of documentation on the finer points of Service Bus 1.0 for Windows Server out there... I'm hoping some of the MS insiders can help clear a few things up...

  1. Do services utilizing queues/topics run in an implicit, ambient transaction? For instance consider the following code snippet:

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

    In the above sample, without creating an explicit TransactionScope, would DoDatabaseWork() be committed if DoMoreDatabaseWork() throws an exception? In other words, does the queued operation run under an ambient transaction tracked by MSDTC?

  2. Do Service Bus 1.0 queues automatically retry if an exception is thrown (like MSMQ does)? I ask because I haven't come across any .config setting for the netMessagingBinding that specifies retry behavior. Also when creating queues using Service Bus Explorer the closest thing I see is MaxDeliveryAttempt. Coming from an MSMQ background, I'm used to seeing exception messages appear in the retry/poison queues. Is there something synomomous with this in the Service Bus 1.0 world?

Thank you in advance

UPDATE:

Please see my answer below for more details. I am modifying this question to ask the following:

Is it possible using contract-first, IIS-hosted, WCF with Service Bus 1.0 to 'cover' client sending to the service bus in a transaction? If so, how? Also, what is the mechanism that is used?


回答1:


I believe I've found the answer to both of my questions...

  1. For Transactional operations, i don't believe there is an "ambient" transaction. I've proven this by simply throwing an exception after a database operation, and sure enough, the data is committed anyway. I would like to know if there's a preferred method of declaring transaction scope, i.e.:

    [OperationBehavior(TransactionScopeRequired = true)]
    public void MyServiceOperation(){ ... }
    
    //or using the TransactionScope
    
    public void MyServiceOperation()
    {
        using(var transScope = new TransactionScope(...)){ ... }
    }
    
  2. For retry functionality, it looks like you need to enable the ReceiveContext, following 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("...");
        }
    }
    

UPDATE:

After digging a little deeper, I've found that the OperationContext` completion isn't really an option if you're using plain vanilla, contract-first, IIS-hosted, WCF with Service Bus 1.0 (not sure why, but I'm hoping someone could shed some light on this)

What I have found is about the only sane option for transactional behavior is the following:

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

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

The problem remains that this pattern, unlike say MSMQ, does not allow for the entire operation to be rolled-back if sending the message to the service bus fails. (unless of course, someone out there knows better...)

This also means you're forced to roll-your-own retry logic and likely some mechanism to verify at the next step that the previous step was committed. YUCK!

From what I understand, Workflow Services and dealing directly with brokered messages gives you some out-of-the-box retry capabilities. But if you're IIS-hosting your Workflow Services with IIS via AppFabric, then somehow Microsoft figured out how to get the transaction to cover sending to the Service Bus. (If anyone knows what that mechanism is, please let me know!)




回答2:


For #2, you can get retries through Transient Fault Handling Framework

http://windowsazurecat.com/2011/02/transient-fault-handling-framework/

Read through this document for usage related to the Service Bus.

http://social.technet.microsoft.com/wiki/contents/articles/best-practices-for-leveraging-windows-azure-service-bus-brokered-messaging.aspx?Sort=MostRecent&PageIndex=1



来源:https://stackoverflow.com/questions/15509955/service-bus-1-0-for-windows-server-transaction-error-handling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!