I was doing a bit of a thought experiment recently about the effects of reliability on performance. Basically I wanted to know a) will WS-RM affect the performance of my application and b) how does it compare to a RESTful HTTP approach. The quick answer is that it depends (like most complex questions in life).
WS-ReliableMessaging
In the RM case the first question that needs to be asked is what type of message exchange patterns am I working with?
- One way?
- Request/Response?
- Small messages? (< 1K)
- Large messages?
WS-RM specifies that we receive a <SequenceAcknowledgment> for every N messages. If we are using a request/response this gets combined into the SOAP response headers. If we have one way messages we’ll receive a new SOAP Envelope every so often with just some acknowledgement headers. There will also be a <Sequence> header with each request message. And if you aren’t already using WS-Addressing, headers will be inserted for it on both the request and response.
In a typical service invocation we have the following items which consume our processing time:
- Processing of WS-RM + Addressing headers. These end up being around 600 bytes total.
- Processing of request and/or response messages
- Time spent in transport. For this example we’ll use HTTP.
- Time spent in service
Right away, we can see if we’re dealing with large messages, RM will have very little performance affect on our service. Whats another 600 bytes if you’re already sending around 20K?
So lets look at what might be the worst case: one way message which are < 1K. For 1K one way messages HTTP ends up being about 30% of the processing time (roughly). Lets also assume for now that your time spent in the service (i.e. doing database stuff) is negligable.
Performance degradation = (1K*1.3 + .6K) / (1K*1.3) = 146%
The “*1.3″ is to factor in HTTP processing time – which ends up being the equivalent time of processing a .3K message.
Its important to remember that this completely disregards server side processing time, so I think the worst case for a 1K one way message is probably more around 30% degradation in performance. For larger messages its probably safe to assume that it will probably have a 5% or less performance impact.
Acknowledgements
You may have noticed this completely ignores acknowledgements. For now I’ve assumed those will only occur every so often, so they won’t have a huge performance impact. If we look at the extreme situation, I can see where we might have 100 clients, each sending 1-2 messages per second. How many messages will the server want to buffer here? If these are small messages and we end up acknowledging ever 3rd or 4th message, this could have a big impact.
HTTP with Idempotent Methods
We should also be able to achieve reliability through idempotent methods. PUT and DELETE are idempotent which just means we can “attempt to transfer our state” (aka submit our data) as many times as we’d like – until we receive a response code. Any time we’re retrieving data, we can issue GET as many times as we’d like as GET does not change the server side state.
Right away its clear that if our application is only retrieving data, the RESTful HTTP approach does not have any impact. We simply issue GETs and don’t do any extra work. Of course, if you’re only retrieving data you probably wouldn’t enable WS-RM because it wouldn’t add muchh value there either, so this really isn’t an interesting case.
Lets say I want to submit an order for some widgets. This will become a two step process with HTTP. First, a POST to /widgets/order. This will return a URL to a place we can PUT our order – i.e /widgets/order/abc-123. The server will listen at that URL for new orders and only accept one order there. The client will submit as many times as it needs to.
Performance does degrade here as it involves an extra POST. The degradation is probably comprable to the one way small message case in WS-RM, but I don’t have any numbers handy to prove that. The nice part is that you only take this hit when you’re actually transferring state. If you’re application is 90% GETs then you probably won’t see a huge impact here regardless of your message sizes. On the other hand if your application is continually submitting data this approach will probably have an impact.
Conclusion
Each approach can be made to work I think. Which one you chose probably depends on your application and use cases. Are you sending lots of data? Are you only retriving data? Also, what about interoperability, ease of use, and integration with existing architectures? And we haven’t even touched the possibilities of using something like JMS or OpenWire here. It seems performance is just one question of many for service builders.