Sunday, July 6, 2008

Transactional Services (continued...)

In my last post we discussed the concept of transactional services and how they ensure business actions can be executed atomically within a service by enrolling local queue and/or topic resources into a distributed transaction. What I did not explain however is why queues and topics are essential for supporting transactional services.

Queues and topics are necessary to support transactional services because that both types of transports queue messages while they await delivery. Although the transport may not store messages durably, they are still stored somewhere until they are delivered. Neither the sender nor receiver holds onto the message during its transport.

So, would it be possible to implement transactional services using a non-queued transport? For example, let us assume we wanted to use WS-AtomicTransaction (WS-AT) over an HTTP transport. As it turns out, it is not possible to achieve this without spanning the distributed transaction across your service boundaries. As we all know, spanning transactions across service boundaries is not a good idea as it hurts performance and reliability.

The reason for this is that with queued transports, messages are delivered to the receiver using a pull based mechanism. Messages are first pushed to the receiving queue, after which they wait to be read by the receiver at a later time. This means that the sending service can complete and commit its transaction without concerning itself with the success or failure of the receiving service.

Moreover, queued transports will cache the outbound message locally making the availability of the receiver irrelevant in committing the local transaction. Without this mechanism for storing messages as they are transported between services, the successful transport of the message as well as the successful execution of the operation at the receiver become relevant as to whether the local transaction can be committed at the sender.

Consequently, the sender must wait for a response from the receiver before committing the transaction - during which time local resources will likely be locked as part of the local transaction.

So although transactional services are an incredibly powerful tool in service design, they do unfortunately require the use of a queued transport.