Skip to main content

Messaging vs. RPC? Let's fuse 'em.

Posted by cajo on June 19, 2008 at 6:58 PM PDT

What is the fundamental premise of messaging, and how is it different from RPC?

Essentially, messaging focuses on the concept of loosely coupled, event/information delivery; between one or more producers, and one or more consumers. RPC focuses on the concept of tightly coupled synchronous functional invocation; between a client and a server. What would happen if we applied cajo technology to coalesce these two concepts?

This is precisely what the newly updated cajo Queue class does. Queue instances are initially constructed by providing a topic object. This object is a mutually agreed upon class, between producers and consumers, which provides the context for why the community is using this particular Queue instance. For example: the topic object could be something as simple as a string – "Wine Enthusiasts" or as elaborate as a HashMap of subtopics and values.

Consumer objects can be either local or remote to the JVM in which the Queue object is operating, and register using its enqueue method. Producer objects can also be either local or remote, and create events by invoking arbitrary methods on a Queue object reference. These invocations return immediately for producers; and are asynchronously invoked on all registered consumers. The invocation's successful return to the producer, guarantees that the event has been accepted. As the object's name implies; producer invocations are queued, as necessary.

For example:

// Producer actions:


queue.ping(); // invokes the method ping() on all consumers

queue.position("37.391008, -122.082073"); // new location

queue.fill(x, y, width, height, Color.red); // mask area


// note: queue does not implement any of these methods itself

// they are invoked on the consumers, only if they support them

The real gist of fusion takes place in the concept of method invocation on the Queue object. A producer may invoke a method taking no arguments; this is traditional notification messaging. A producer could invoke a method taking a single argument; this is traditional data messaging. Finally, a producer could invoke methods taking multiple arguments; this is traditional RPC, but loosely coupled, i.e. functional messaging -- exhibiting three key features:

* The function signatures are independent of any class or interface definition

* The potential one-to-many relationship, between the producer and its consumers

* The consumer is not required to implement the functions being invoked by the producer

The Queue class performs the consumer invocations asynchronously from the producer's; it discards any direct return values, and exceptions from the consumers. Therefore, if the producer wanted feedback from consumers, it could provide a callback reference as an argument, for example.

If there is only one producer, and one consumer, this is what is commonly referred to as point-to-point messaging. When there is one or more producers, and more than one consumer; this is what is commonly referred to as publish/subscribe messaging. With the Queue class approach, these are just variations in how the object is used.

Lastly, just for fun, the Queue class is serialisable, meaning Queue objects can be passed between JVMs at runtime, (i.e. cloned) whilst retaining all producer and consumer links. The possibilities created by this, are nothing short of mind-boggling. ;-)

Best of all, Queue is implemented in a single class, consisting of less than 100 lines of code. I recommend giving it a try; it is extremely simple to use, highly intuitive, and very powerful. It is a handy new tool, to add to your kit.

Enjoy,

John

Related Topics >>

Comments

Hello John, I wrote three articles (in french) about cajo and the Groovy language, here on my web site: http://www.odelia-technologies.com/cajo. I also introduce a Groovy class, CajoProxy, that uses Groovy metaprogramming in order to obtain more concision and clarity for managing cajo items. So, for example, to publish an event on a Queue object you can really write queue.ping;! Bertrand Goetzmann http://www.odelia-technologies.com

Hmm... I don't get where the big news are - probably I'm not understanding something, probably I don't know enough about Cajo. This sounds just as an "asynchronous, distributed listener" that I've seen elsewhere, and personally used with Rio + Jini - the "publish & subscribe" implementaiton seems to be an application-level responsibility of listeners, or am I missing something?

BTW, the simple background Thread proved to me to be not good in many real-world cases, e.g. when you use TCP connections (I suppose Remote.invoke() is done through TCP) and you have time-outs (eg. because a connection cable has been unplugged). You usually get 10-20 sec. timeouts in the socket that is blocking and delaying the next listeners in the queue - so something more complex, such as a pool thread delivering in parallel, is needed.

Hi Fabrizio,

Thanks for your reply! :-)

The news, and not that I'm saying it's big news, is singularly and asynchronously invoking methods on multiple objects. I know I am not the first to think of this, it is far too fundamental a concept. Rather, this is an approach to achieving it, which I believe to be somewhat simple and intuitive. Publish and Subscribe are interestingly reversed; each Queue instance represents a single topic, rather than the traditional "omni-subject" object, to which consumers indicate their specific interests.

For the first two cases of invocation; data-less, and single-argument; yes: I suppose you could consider the consumer objects "listeners." However, in the third case, When methods are being directly invoked on the consumers -- I believe a much richer, yet far simpler mechanism for consumer interaction is being provided. To be sure, you could provide a single XML SOAP message, and have the consumer decode it to perform the same functionality; yet this approach seems so much more natural. It allows all involved parties to be simple POJOs.

Most importantly, you are correct: The simple background thread implementation is to prove the concept, it could be quite adequate for many small Queue objects. However, if you wish to create a large-user Queue instance, more sophisticated techniques would indeed be necessary.

Thanks again, all the best,

John

Well, since it's been 2 years, I'm going to stir the pot, I want to turn the argument upside down.

I will assert that Synchronous RPC is, in fact, a degenerate form of messaging.

Why is that?

Well, when considering ethernet, what is the more primitive form of IP? UDP is more primitive than TCP. Why is that? It's unreliable, so it's lighterweight. It hasn't the guarantees of TCP.

How does TCP work? It takes a message packet and blasts it off in to the ether. Then the driver goes off and goes to sleep.

When the ethernet card detects a signal of an incoming packet, it alerts the driver. The driver reads the packet to see if it is, in fact, a acknowledgement of it's previously sent packet.

If it is, then all's good and it sends more packets. If not, it keeps waiting until some time out when it either tries again, sending another packet blindly on to the wire, or eventually giving up and returning an error to the caller.

It's all done using asynchronous techniques at the protocol and media layer. Hell, even RS-232 is asynchronous.

All reliable messaging protocols are based on a "can you hear me now" send/receive protocol. That's the best way they can be reliable (you can send a lot of extra data that lets the receiver potentially rebuild the data stream with all of the extra error correction information, but that tends to expand the data stream. Good for talking to space craft, not so good for high volume data streams.)

I know, a little off topic, but...anyway

John,
I am reminded a bit of interesting tools looking for problems to solve, but maybe I'm missing something (or maybe this *is* your point).

Are you thinking of anything that can benefit from this hybrid approach? Specifically something whose solution is materially improved by the "hybridness"?

Hi Will!

(Wow, I can't believe it's been two years already; my, how time flies!)

Stiring the pot is a good thing, from time to time, and I think now is a very good time. :-)

Yes, sometimes upside down, is indeed a very good way of looking at things!

At the "atomic" level, all communication is based on packets, i.e. "messages".

(You know what RS-232 is, you must be an old-timer, like myself ;-)

I agree with you, and I'll even go so far as to assert that RPC is a higher-level abstraction, based on TCP messaging: However, most of what is commonly referred to as "messaging" these days, is ironically based upon RPC.

As always, thanks for your insightful input,

John

Hallo Bertrand,

Thank you for looking into cajo, many think it offers very real potential.

If you look at the static void main method in the Queue class, it shows two different methods of connecting. First, it registers itself with the host machine, therefore, a producer or consumer, could have a directory of hosts on which to find these objects. Second, the Queue object can "announce" itself over UDP, allowing other listening machines to discover its existence.

With regard to Groovy; unfortunately I haven't yet the time to look into it. I would welcome however, someone who wanted to provide an example of scripting cajo with groovy. ;-)

Alles Gute,

John

Thank you for your article. cajo is very interesting! If I understand well, for the server part, you must create an instance of Queue and export it using a Cajo instance (I've read your article "Simple Inter-JVM communication... The Grail! "). How can a client can discover this instance? In fact, I would appreciate an example. Another question about scripting with cajo: do you have a look to the Groovy langage? With cajo it would be a powerful combinaison! You can take advantage of its Meta Object Protocol (one example, the Groovy XMLRPC module: http://docs.codehaus.org/display/GROOVY/XMLRPC). Bertrand Goetzmann. http://www.odelia-technologies.com/

John, have a look at request/reply messaging in JMS, and in messaging systems since the 1980s. See http://java.sun.com/javaee/5/docs/api/javax/jms/QueueRequestor.html . It's fun, but Sun's nailed down the right API for this long ago. Why not build on that?

No, you are not missing something, that is my point.

This technique is offered merely as a design pattern; not pointed at any specific problem, rather as a powerful resource, for when challenges arise. Should I create a specific application of the pattern; you can rest assured that I most certainly will publish it. ;-)

Both RPC and messaging are used a lot in practice, but very rarely together. I simply propose that there is potential new opportunity in combining the concepts.