Archive

Archive for the ‘Service Broker’ Category

WCF Transactions - Treat with care.

November 13th, 2008 Simon Segal No comments

The most canonical example usage of WCF Transactions (according to Juval) is the following :

A client application wraps (n) service calls in a single transaction and relies on the ACID safe haven of System.Transaction to save the day. In my opinion, one of the core characteristics of WCF is that it’s design favours (and Microsoft like to demonstrate it’s usefulness via) a remote object pattern where developers program against an objects polymorphic signatures i.e. its behavioural aspects, via a proxy. This can be seen when we consider code such as proxy.UpdateAccount(); or proxy.RemoveCustomerPurchase(Guid purchaseID); for example, where proxy is a variable name for an object classed from a CustomerAccount class or more precisely implementing the ICustomerAccount interface and it’s operation contracts. Why am I highlighting this design characteristic? It’s my view that this characterstic has permeated it’s way into the entire design of WCF and it’s impact is felt an many corners of the Platform and affects us for example in the choices we are required to make on concurrency and instancing, however before we get into that let’s look at the example below as per the canonical example.

Figure 1.0

canonical_wcf_transaction

Listing 1.0

public void Call_A_B_C(Guid purchaseId)
{
    //…..create the binding and the addresses
    ChannelFactory<ServiceA> factoryA =
        new ChannelFactory<ServiceA>(bindingA, addressA);
    IServiceA channelA = factoryA.CreateChannel();

    ChannelFactory<ServiceB> factoryB =
        new ChannelFactory<ServiceA>(bindingB, addressB);
    IServiceB channelB = factoryB.CreateChannel();

    ChannelFactory<ServiceC> factoryC =
        new ChannelFactory<ServiceC>(bindingC, addressC);
    IServiceA channelC = factory.CreateChannel();

    using(TransactionScope scope = new TransactionScope())
    {
        channelA.RemoveCustomerPurchase(purchaseId);
        channelB.UpdateInventoryRequest(purchaseId);
        channelC.AmendBillingNotice(purchaseId);
        scope.Commit();
    }

    //…..etc
}

Let’s also assume that our Services A, B and C have the following Transaction flow attributes setup correctly so our client initiated (ambient) transaction flows through to the services.

[ServiceContract]
public interface IServiceA
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    public bool RemoveCustomerPurchase(Guid purchaseId);
}

public class ServiceA : IServiceA
{
    [OperationBehaviour(TransactionScopeRequired = true)]
    public bool RemoveCustomerPurchase(Guid purchaseId)
    {
        //…Database access etc…
    }
}

The idea here of course is that calling all three services in a single transaction will make our services behave in a way where the state of our systems (most likely kept in a database repository) will remain consistent in the case of a failure at any point through the transaction - it’s an all or nothing proposition. Combined, this aggregation of requested operations represents a discrete logical business workflow of some kind, where all operations or business actions must succeed or fail as a single ATOMIC transaction.

Again let’s note that these (three) operations (service method calls) are modelled more like traditional business object behaviours and will likely include some database interaction (we will talk about the File IO in figure 1.0 further on) and other potentially long running code. These operations typically implement a request / response message exchange pattern and by lining up all three of these requests inside a transaction and locking resources we are immediately creating a friction with our ability to scale and increasing our chances of encouraging database deadlocks and service  timeouts. Also worth noting is that the default IsolationLevel for the TransactionScope is Serializable which happens to be the most expensive Isolation Level and will lock whatever our service touches until it’s finished doing it’s work.

As a consultant I have seen my share of Web / WCF Services running out there in the wild and it’s pretty common to see them spread over a variety of IIS machines and in some Windows Services running under the SCM and furthermore some of these services are large (have hundreds of operations) and have lots of database access code and they all hit the same tables in the same DB’s in any variety of order. For example, in our example above, it’s not uncommon to see Service A, B and C all accessing the same database and tables and it’s also common for a variety of disparate applications to use all three services independently and not in a universally consistent manner. Lets say we have client X which uses Service A and C and client Y which uses Service A, B and C and client Z which uses Service A only. Imagine that these client applications use any number of permutations in aggregating service method calls within a surrounding transaction; while these long running operations are having distributed locks applied to both the services and database queries, other client requests are waiting and become more likely to timeout.

This approach does not scale. So let’s imagine we are using RepeatableRead for an isolation level (not the default Serializable) and we have multiple clients making distributed transaction calls across services, all the locking going on in the database is going to slow things up and our services will be waiting for locks to release, which in turn will make our clients wait for our services to return responses and gradually our system will grind and timeout, suffering more and more as further users come on line. Their is an underlying complexity with WCF declarative architecture, many configuration options that can be strung together to state an intent about instancing concurrency, ATOMICITY, transport characteristic, security and the list goes on. Sometimes its possible to create a collection of declarative statements that are acceptable however when applied are redundant or countermanding. It’s possible in the scenario we are discussing that service operations under load be queuing up calls and locking out other clients whilst this potentially weighty transaction is occurring across different web servers and databases and should one of them start to cave in under this load then our system is going to spiral down and every part of it will probably become non-responsive. In the meantime who knows how many important messages are being lost on the wire without any store and forward strategy. These are indeed some of the reasons that distributed transactions are a bad idea and that it may be worth considering transactional asynchronous messaging in these scenarios. Store your message and then get it across the wire under a transaction (so it’s not lost) letting each endpoint worry about storing their own messages and processing them under the steam of a different thread than that managing the Service method. You could of course use MSMQ binding but it’s a limiting design choice and if you require HTTP as the transport it’s not viable. Also, if you have to deal with state at the point of handling the message, then Separating the threads or perhaps even the processes for dealing with the concerns of receiving the message and handling messages, makes for a more scalable and performant system, lending itself well to dealing with long living service state. Perhaps your service design includes dealing with various messages over time, where the messages need to be correlated to one another as in a Saga.

Client passes message and flows transaction to >> Service A >> Service A passes message and flows transaction to >> Service B >> Service B passes message and flows transaction to >> Service C. Now if anything goes wrong in the hops between client and services here then we expect everything that happened to be rolled back right? Wrong! With ASMX or WCF out of the box bindings that don’t include MSMQ, there is no durable storage of our messages, so if the client below in Figure 2.0 sends an order, something goes wrong somewhere and we roll back, we just lost our message (hope it wasn’t an order right?). Furthermore, in Figure 2.0 we could add more clients which use any one of the services depicted exclusively, for example Client B comes along and calls Service C only, meanwhile the depicted client (A) is making an distributed transaction across aggregated calls to Service A, B and C where it currently is waiting for Service A to complete its work. Service A (on behalf of client A) is accessing the same database table as Service C (on behalf of client B) - there is a deadlock in the database, a victim is chosen and someone rolls back, however whilst they were blocking and the transactions were open on our Per Call, Single entrant WCF Services, all the other clients requesting work were held up and waiting and potentially timed out as well.

Figure 2.0

trans_a_b_c_services

It’s generally a good idea to keep your transactions in WCF open for as short a period of time as possible and that’s why using WCF as pure message transport (i.e. absolutely no business logic or database interaction) can help you achieve better throughput, scale and be more fault resistant. Transport your messages transactionally from queues (where the message originates) and to other queues located at the message destination, this will protect against lost messages; it’s possible to use WCF entirely as the transport protocol enabler of choice and not follow the CRUD RPC styled messaging pattern.

Figure 3.0

wcf_transactional_messaging

Because we read the message off the originating queue and send it to target queue within the scope of a transaction, our message will simply roll back of there’s a problem. If we pursue the concepts outlined in Figure 3.0 to their conclusion, we might consider MSMQ or SQL Service Broker to provide us with our Queues and Service Broker does offer us some potential Smart Client benefits in being so close to our endpoints in this design scenario. Let’s be clear however, we are proposing using Service Broker for it’s queues and only it’s ability to provide queues, we do not propose to build services, contracts et al in Service Broker, thus avoiding any ensuing licensing issues which Service Broker will create if you implement your services using that technology.

Share/Save/Bookmark

Categories: SOA, Service Broker, Services, WCF Tags: , ,

Oslo, SOA, BizTalk Express & crossing the chasm.

July 7th, 2008 Simon Segal 8 comments

So what exactly are MS up to with the Oslo initiative? We certainly know a fair bit about the Internet Service Bus (ISB) but that isn’t the whole story. WCF has been with us now for some time and is certainly being adopted with a fair amount of vigour, however, lets be fair, the amount of ’stuff we need to know’ that has crept into developing services (WS* etc) is becoming increasingly burdensome for software teams to maintain, heck Juval is saying that it’s (WCF) as big as .NET itself (I should learn 2 .NET’s?). Where should I turn? BizTalk? Yikes! In all seriousness I am currently investing more time to master BizTalk, but let me say it’s a narrowly focused and targeted strategy, where I plan to take advantage of the products sweet spots where the right circumstances are present. It is simply not realistic to choose WCF or BizTalk as an exclusive method of messaging. Scaling BizTalk is an expensive option and if I’m looking to use messaging (not the WCF or ASMX RPC styled request / response) then I need some options.

Variety is the spice of life.

Indian_SpicesNServiceBus is a great option (and it’s free), other vendors  provide more heavy weight (smart network ESB products) and Microsoft currently offer BizTalk & Service Broker when it comes to messaging frameworks / products. Lets face it the Microsoft options are expensive if you want out of the box Pub / Sub across the organisation or Enterprise. I could roll my own bussing architecture but that’s expensive and risky, I recently called for BizTalk Express so I could distribute a messaging solution without the expense but something tells me that I might not see that product in the near future. What I want is a simple bus framework that isn’t overly weighed down in complexity (NServiceBus fits the bill again) and I get the feeling that Oslo will provide me with a set of tools that are not going to be very different from a technological aspect, rather will deliver a set of guidance with some new frameworks & integration points that utilise current technology - the ISB working hand in hand WCF everywhere and BizTalk for arguments sake.

Good things come to those that wait?

Certainly I will continue to use WCF and WF where it makes sense and I will use NServiceBus where warranted but in the meantime I will continue to wonder about what Oslo will deliver. How far will it reach into the tooling and the API? All this is yet to be seen but we live in hope and anticipation. Certainly BizTalk is now beginning to cross the chasm but an Express version would have it make leaps farther than Carl Lewis on Ben Johnson’s dietary fibres.

Share/Save/Bookmark

Viable SOA Queue Alternatives

May 23rd, 2008 Simon Segal No comments

Some of the most visible Service Bus (open source) frameworks around in the DotNet community, utilise MSMQ as their choice of queuing technology. MSMQ usually gets a look in as both a store and forward mechanism and endpoint in those cases. Most would say that the options in the choice for a queuing technology are somewhat limited when it comes to being free and hence we see MSMQ fit the bill here more often than not.

It strikes me however that SQL Server Service Broker IS an option in solving this problem and in doing so we might gain some nice value added benefits . The objections to using SSB in architecting SOA solutions are generally that a multiple SQL Express Service Broker peer solution isn’t possible and that the alternative of having to use Standard or Enterprise Editions might be cost prohibitive (depending on your organisation). This complaint presupposes our intention would include using SSB features such as Services, Conversations / Dialogs etc and that ALL the messaging infrastructure would be taken care of by the out of the box SSB feature set.

Some other possible improvements on the MSMQ scenario are less friction in deployment, backup and administration, not to mention the benefit of having an instance of SQL Server close to applications that might actually be smart clients.

I feel some of my spare (?) time being lost in following this thought and moving it to code!

Share/Save/Bookmark

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia