Inspirel banner

Types Of Middleware

Introduction

This article is an attempt to define several distinct types of middleware. The reason to do so is to set up a necessary foundation for other discussions related to this subject. An important part of this motivation comes of course from the fact that the flagship product of Inspirel is YAMI4, which is a set of communication libraries for distributed systems - it is reasonable to define its place in the wider ecosystem of middleware solutions.

Obviously, this article is limited in scope and cannot cover absolutely all possible solutions that exist on the market. In fact, a very small sample of existing solutions was selected. Hopefully, the differences between them are so clear that even though the selection of products is purposedly limited, they already allow to partition the world of middleware systems into quite distinct areas - this is enough to define the target for YAMI4.

As a common vehicle for discussion, the following distributed problem is taken: sending the weekly work report to one's boss. This problem can be solved in a number of ways and the focus of each particular solution is taken as a distinguishing factor for grouping middleware products into distinct types.

Object-Oriented Middleware

An object-oriented middleware focuses on the receiver.

Most of the effort in object-oriented systems goes into the management of concepts that are directly related to the receiver of some message or stimulation. These concepts are:

The object-oriented middleware will try to solve such problems by focusing on the receiver of the message and by introducing tools like remote object references or proxies so that the object-oriented "look and feel" is preserved at the call site. Even though not strictly necessary, that last notion is taken very seriously and the effect is that typically remote invocation will not look much different from the local one:

boss.process(myReport);

Above, the method invocation syntax does not reveal the distributed aspect of the whole operation and this is done on purpose - to bring the boss and his behavior to the front and hide unnecessary details behind his interface. The middleware platform will typically use some static interface description in order to facilitate this level of integration with generation of appropriate proxies.

An advantage of such encapsulated approach to communication is that the distribution of the whole system becomes a deployment issue and is not necessary to deal with in the coding stage. That is, the above line of code can be written the same way whether the system will be distributed or not. On the other hand, isolating the programmer from the physical aspects of the distribution at the coding level just makes it more difficult to properly handle those aspects.

Examples of object-oriented middleware systems are CORBA (omniORB, TAO, etc.) and ICE.

Service-Oriented Middleware

A service-oriented middleware shares a lot with object-oriented approach (also in terms of physical workflow), except that there is less focus on the target of invocation and more on the operation to be performed. In the case of weekly report problem, the service-oriented middleware would put most of the effort on defining the operation (processing the report) and perhaps the data structure that is being sent or received (the report itself) - but the user of such a system would not be concerned that much with the receiver.

Service-oriented middleware can be expected to be a lot simpler than object-oriented one due to the fact that lots of expensive problems - like identity and lifetime of remote objects - do not have to be solved at all.

Thrift is an example of a service-oriented middleware.

Data-centric middleware

A data-centric middleware focuses not on "who is talking" but rather on "what we are talking about" - that is, the focus is on the purpose and meaning of data that is subject to transmission.

In the data-centric middleware most of the effort is spent on ensuring effective routing of information to all interested parties. In the case of weekly-report problem, the sender is concerned only with publication of his content and the middleware takes care of the rest. That is, the sender should not be concerned with who will ever receive his content - which might be anything between zero and many receivers. Presumably there will be somebody (a boss, perhaps?) interested in the weekly work report that was dutifully prepared and published by the sender, but this assumption belongs rather to the configuration aspect of the whole system than to the manner of communication. In this sense, the data-centric middleware is similar to how radio stations operate - they just produce information and consumers tune themselves to the channel that is of interest to them.

This decoupling of communicating components has both advantages and disadvantages. On one side, decoupled components are less sensitive to individual failures and it is easier to construct resilient architectures at the higher level. On the other hand, decoupling makes it inherently more difficult to set up communication in the request-response manner (typical for client-server interactions), which would be more natural for some problems.

A data-centric middleware does not have to be tied to the idea of hiding the physicality of communication from the programmer, like in the object-oriented approach. The distribution is already more or less explicit by the nature of publishing or broadcasting, and the middleware can therefore offer quality of service control so that various physical aspects like time or bandwidth can be properly managed. Still, the data itself remains at the center of this communication paradigm.

Examples of data-centric middleware systems are all DDS implementations (OpenSpliceDDS, OpenDDS, RTI DDS, etc.), AMQP brokers and JMS. They are frequently installed in those distributed systems where potentially many receivers can be interested in data produced by individual sources.

Message-oriented middleware

A message-oriented middleware differs in its focus from all previous ones. It is not the receiver, not the operation and not the data that is being put in front as the communication paradigm, but rather the fact of communication itself together with its physical aspects like size and time.

This difference in focus is very important, as it can influence the capability of the user to properly handle the communication in the context of its physical limitations. The idea is that in message-oriented middleware the communication is not hidden or encapsulated - which would be typical for object-oriented approach - but exposed at least to the extent that allows it to be managed. In particular, the fact that it actually takes time to send something to remote location is visible in user code.

Message-oriented middleware has an analogy in the operation of traditional post office services. Customers can send a mail or a package to some destination and get a receipt that allows them later to track the delivery progress. It is this receipt that identifies the mail or package and it is also what gives the focus on the process of delivery. This analogy allows to contrast the message-oriented approach with object-oriented one.

Again, the object-oriented code example:

boss.process(myReport);

The concept of delivery and physical aspects of the whole communication (like the passage of time) are completely hidden from this syntax, as the syntax was intended for local invocations, where the cost of delivery is negligible. As a result, the programmer has very limited capabilities in managing the physicality of the message delivery - for example, it is not possible to track the progress of sending big message this way. A simple time-out with an exception that forcibly disrupts the call is probably the only thing that the object-oriented middleware will offer, as there is simply no place in this local-like syntax for any more elaborate management of time.

A message-oriented approach to the same problem will instead focus on the message itself:

Message msg = middleware.send(boss, myReport);
// ...
msg.wait_until_confirmed();

The above syntax is artificial and might not correspond to any existing system, but highlights the analogy with regular post-office services. The msg object is a handle or "receipt" that allows the user to later track the delivery of the message - for example, to show the progress of transmission in a graphical way or to check how much data was actually involved in the communication. Or, to check in a completely asynchronous way whether the message was delivered and processed at the target side. In any case, the user deals with the message as a primary artefact of communication.

A very important consequence of exposing the physicality of messaging - in particular the passage of time - is that it becomes easier to deal with. In the above example it is clearly visible that something possibly lengthy is happening between two lines of code. By giving the user an explicit handle to this process (instead of hiding it behind object-oriented syntax) the message-oriented middleware makes it easier to decide how these lines should be organized. The following code examples show one possible way this freedom can be used.

Two messages can be processed in sequence (one completed after another):

Message msg1 = middleware.send(somewhere, something);
// ...
msg1.wait_until_confirmed();

Message msg2 = middleware.send(somewhereElse, somethingElse);
// ...
msg2.wait_until_confirmed();

Alternatively, the same two messages can be processed in parallel:

Message msg1 = middleware.send(somewhere, something);
Message msg2 = middleware.send(somewhereElse, somethingElse);
// ...
msg1.wait_until_confirmed();
msg2.wait_until_confirmed();

Above, a small coding difference can result in fundamental change in how the underlying infrastructure is used, especially in the context of parallel processing and scalability - a subject that is recently gaining a lot of attention.

It might be also interesting to note that message-oriented approach does not limit the other aspects of communication and in principle can support both peer-to-peer interaction in the request-response style (that would be traditionally associated with object-oriented or service-oriented middleware) as well as with decoupled publish-subscribe data transfer. In this sense the message-oriented approach allows to highlight the physicality of communication without any loss of generality.

YAMI4 is an example of message-oriented middleware.