Everything is asynchronous, we have location transparency, everything is very, very fast. But, it isn't reliable. If you care about message delivery you have to think about where things may go wrong, and even though the odds are in your favour that your messaging application will work 99.99% of the time, its always the time that it fails that you should design for. The questions you need to think about are:
- what happens if the broker runs out of resource (memory/sockets/disk space)?
- what happens if my clients loose network connectivity?
- What happens if the hard disks crash on the broker's machine
- what happens in a power outage ?
- etc, etc.
Depending on the size of the message and the quality of the network, a good producer can send tens of messages per millisecond - and it can take sometime (seconds or longer) before your producer realizes there's a problem - your producer client could have just lost thousands of messages and your application wouldn't even know about till its too late. So unless you have smarts built into the client to handle failure conditions (like ActiveMQ does), using asynchronous message publish to a broker isn't always the best thing to do. Its for this reason that the majority of message queue systems support a synchronous publish to the broker, so they can detect failure and resend the message. If you look at JMS, beanstalkd,Gearman, MQTT or STOMP synchronous publish to the broker is on by default. Its a sad fact that AMQP hasn't supported this basic messaging construct before 1.0 of the specification, where at least its optional. Its for this reason the ActiveMQ has not adopted AMQP till this point - you cannot have a JMS compliant product without synchronous message publish. JMS is rightly strict about how the semantics work - in that a receipt would not be returned to the publisher until the message has been received by the store and securely written to storage if its persistent - i.e. guaranteed delivery:
For performance, you could cache messages, and write them to disk lazily if they haven't been consumed, however the very real downside is that the broker could disappear before the message has been stored. Your application publisher would believe the message was delivered, but this wouldn't actually be true if the broker disappeared.
BTW - some people confuse transactions with guaranteed delivery - for messaging, transactions should be used for logically grouping messages together. If you use JMS, never use a transaction to send a single message - its unnecessary.
I'm going to be talking about reliability and performance at an upcoming FuseSource Webinar next week - drop by if you have the time ;)