In-Depth
Getting The Message
- By Max P. Grasso
- August 21, 2001
Messaging middleware is communication software used to create large distributed systems, the same way any other form of middleware is. It is not easy to give even a rough taxonomy of the middleware field; however, if one were to simply classify middleware based on the type of communication primitives it provides, things become simpler. There are basically two “buckets” — the messaging middleware bucket and the bucket of middleware using the remote procedure call (RPC) — and most products (with some exceptions) can fit into one or the other.
In the past decade, the middleware in the second bucket has taken the spotlight by taking many forms, creating many standards and becoming the focus of protracted standards battles. Among the forms of RPC-based environments we can enumerate are OSF DCE, Microsoft’s RPC, CORBA and, in the past few years, the ever-present distributed component environments of COM and Enterprise Java- Beans (EJBs). Each of these basic environments has spawned a host of products, from implementations to value-added facilities. While standardization efforts have made RPC-based middleware a commodity, they have also accelerated the evolution of the functionality and eased its acceptance in development circles.
Middleware in the first bucket, messaging middleware, never really reached the spotlight. Possibly because of this, it was not the concern of any major standardization process and was never the target of feverish development or competition — except for the recent proliferation of messaging products following the release of the Java Messaging Service (JMS) specification. Despite its lack of fame, messaging middleware has been in continuous use in a number of niche apps where its communication facilities provide just the right solution.
The defining characteristics of messaging middleware are:
The well-defined separation of the functions for sending and accepting messages from the functions that carry, route and deliver them; and
The event-handling programming model, whereby application logic waits for messages, receives them, correlates them to past messages (as in the case of requests and response messages) or a context, and then executes appropriate business logic.
A typical business system based on messaging middleware consists of a number of custom applications executing their business logic and communicating with one another via messages. Messages emitted by an application are routed and delivered to any number of other application processes in the system, according to rules and logic defined within the messaging middleware or auxiliary message routing processes.
To get a better understanding of the value messaging middleware provides, we need to dig a bit deeper to get to the common features it affords the systems that use it, namely: loose coupling among application processes; ease of configuring, re-configuring and extending it; and scalability, reliability and persistency.
Loose coupling — Because messaging middleware provides flexible and persistent communication services with which each process interacts (the queues), it allows systems to be made of a large number of processes without falling under the weight of complexity. This loose coupling provided by messaging implies that the behavior of each application process is fairly independent of the state of other processes within the same system. Processes are not aware of any failures experienced by other processes in the system, nor are they even aware of the running state of other processes in the system. This greatly increases the robustness of a system by reducing the failure modes that need to be considered and handled. In contrast, when using RPC middleware, the processes in a system are always aware of their communication partners’ status and often have to take corrective action if a communication partner fails, stops or restarts. This creates a number of failure modes and makes the
system more brittle as it grows.
In fact, a business system built using messaging middleware consists of a number of application processes exchanging messages through an independent communication infrastructure. Each app in the system can be built and executed independently. The global functionality depends on how the functionality of the single app is assembled by configuring queues and communication channels into message flows.
Reconfiguring — Now let us take a look at the second feature provided by messaging middleware: the ease of reconfiguring and extending business systems without making invasive changes to the deployed functionality. How much this benefit is provided depends on the administrative facilities of the underlying messaging middleware product. In general, since each app interacts with the rest of a distributed system through input and output queues, administrative facilities or standard queue manipulation processes can change how an application behaves. A classic example is the addition of a custom message logging facility to a system: Without changing any of the applications in a system, it is easy to interject a logging process as a channel between two queues, one of them being the original destination queue. Alternatively, if the messaging middleware provides message multicasting or publish/subscribe capabilities, one can easily multicast messages to both the original destination and the logging process.
One can easily extrapolate and see the minimal effort needed to extend the business functionality using a number of standard message manipulation functions (duplication, broadcasting, filtering) together with small amounts of custom functionality.
Scalability, reliability and persistency — Finally, messaging middleware may
provide important features to a system, similar to those offered by state-of-the-art
application servers: clustering, workload management and stable storage. Only persistency is now fairly standardized across messaging middleware products; the others are usually proprietary to each product in both scope and implementation.
An example of clustering in the messaging middleware world is provided by IBM’s MQSeries product. It allows queue managers on multiple machines to act in coordination, increasing the service availability of the messaging middleware. Workload management allows the messages to be delivered to one out of a number of destinations based on runtime and configuration parameters — a feature similar to the more familiar load balancing of the application server world.
Persistency assures systems that messages will reach their destination despite temporary failures. In many cases, such assurance is vital and we would not seriously consider any messaging middleware that could not provide it when necessary. But messages can also be lost while they are processed unless queue operations are done within a transaction. To allow single transactions to span multiple queues distributed across the network, and to possibly span multiple databases, a number of messaging middleware products support the industry-standard Extended Architecture (XA) interface. In general, without resource management and transactions, reliable distributed computing cannot be achieved without adding a hefty burden to the application logic.
Transactional message handling
We have stressed the importance of using messaging middleware that supports distributed transaction processing. Let us now look at an example of the importance of using distributed transactions directly.
Consider the case of an order processing system that receives orders as queued messages in the Order Queue. The Order Processing application picks up messages from the queue, updates the Inventory Database by taking the items to be delivered out of it, and sends the shipment order to the fulfillment center by putting a message in the Fulfillment Queue. Now consider the following two failure scenarios and their outcomes.
- The machine running the order processing application suffers a failure after picking up the order message from the Order Queue, but before updating the Inventory Database. In this case, the order would effectively disappear from the system.
- The machine running the order processing application suffers a failure after the database is updated and before the shipment message is sent to the Destination Queue. The system updates the inventory (and may charge the customer), but the fulfillment center does not get shipment instructions.
Assume now that both the DBMS and the messaging middleware are proper resource managers supporting the XA interface for distributed transaction commitment and that, consequently, a single distributed transaction can span the queues and the database. If the Order Processing application initiates a transaction before reading a message from the Order Queue, thereby updating the inventory database, writing the message in the Fulfillment Queue and closing the transaction at the end — then the three actions are either successfully completed or, in the case of failure, none of them is. Either outcome is acceptable; the consequence of a failure is that the message will be reprocessed by the Order Processing app upon restarting.
A component assembly analogy
Messaging middleware allows the assembly of processes by creating communication channels among output/input queues much like you can assemble JavaBeans by creating communication channels for their events (event subscriptions). The analogy maps the processes producing and consuming messages to the JavaBeans, the messages to events. Messaging systems can be seen as the mechanism to dynamically assemble local processes into larger systems, the behavior of which is determined by the local logic and the message flows. Like messages, JavaBeans events can be directed from one component to another, broadcast to a number of components, or filtered by custom logic.
Messaging vs. RPC
Any architectural discussion on messaging middleware will eventually touch on the fundamental difference between messaging and the more widely available distributed computing facilities based on RPC mechanisms or, more precisely, the remote object method invocation. The main difference is in the type of programming and communication primitives they make available.
Modern distributed computing relies heavily on location transparency. Programs do not need to be aware of the location of the functionality they invoke, or that the functionality may be remote rather than local. Location transparency is achieved with RPC. This mechanism is syntactically similar to the standard procedure invocation as it is defined in modern programming languages. Semantically, it is close enough that functionality of one program can often be distributed across a network by changing standard procedure calls into remote procedure calls without substantial design changes.
Like a normal procedure, a remote procedure call transfers execution control from the caller to the called entity. While in the normal procedure case the execution context is provided by the stack, in the remote procedure case the RPC middleware gives controls to the called procedure after building a computing context that includes the procedure parameters at a bare minimum; but it can often include security, transactional and other attributes. This transfer of computing context allows the remote procedure to execute almost as if it were in the same process as the caller. The control flow is transferred back to the caller when the procedure returns. The RPC mechanism enforces this behavior by suspending the calling thread after having sent the procedure call message and letting it wait for the return message. The caller, upon receiving the return message, resumes processing within the same context in which it sent the call. The only difference is in the return values of the remote procedure call. Everything works as if the call is a normal procedure call; the only kinks are in the management of communication failures and possibly of memory resources.
Because the RPC mechanism forces synchronization of the communicating process on the call message and the return message, it is classified as a synchronous communication mechanism.
Remote method invocation
A more often used descendant of the RPC mechanism, called remote method invocation (RMI), facilitates the distribution of object-based systems across the network. All that is required is the use of specific object factories rather than language-specific constructors whenever an object is to be reached transparently within the same process or across the network. The object provided by the factory is either a local object or a proxy to a remote object — something the object’s client need not be aware of. In either case, methods are invoked using the syntax of the object-oriented language in use.
Currently, the remote method invocation mechanism is the accepted basic communication mechanism for distributed component systems, used to carry requests and responses across components.
COM and EJB components inside Windows mostly communicate via local or remote object method invocations. CORBA also uses remote object method invocations. These models also take full advantage of the characteristics of RMI to transparently provide a transfer of security, transactional and other contexts.
Asynchronous communication
Given all of this, why would we ever consider using something other than remote method invocations?
In reality, the transparency and contexts transfer of remote method invocations come with some performance overhead and are not always useful; at times they may be an issue. More concretely, when messages cross the enterprise boundaries, one rarely wants to inherit the source security or transactional contexts, since the enterprises on either end of the communication almost never belong to common security or transactional domains. Rather than accepting transparent transfers of context, applications operating at the enterprise boundary often require close examination of incoming and outgoing messages to make sure that they are not only syntactically well formed, but abide by application-specific security policies (for instance, all message requests for transactions above a specific amount may need to be signed using specific certificates).
Finally, by its very nature, the RPC mechanism forces the caller to wait for procedure calls to return. This causes difficulty when the procedures require long execution times. Because the caller needs an execution thread for each outstanding call — and threads are not cheap — synchronous computing mechanisms can easily hit a brick wall.
Synchronous processing hits a brick wall
A fairly common example of this is a Web server doing a remote method invocation against a CORBA server to process credit-card payments. Usually a Web server has a pool of between 50 and 100 processing threads. Let us assume 100 in our case. Also assume for the example’s sake that the credit-card processing procedure takes about five seconds. If 100 Web requests requiring credit-card processing were to occur within a five-second period, the Web server would become incapable of processing any more Web requests of any nature, since all its threads would be waiting for the credit-card processing procedure to return.
To solve this problem one may attempt to reduce the procedure processing time, but that is not always possible. Or one may change the semantics of the procedure so that it returns only after enqueuing the credit-card processing request, which allows the calling threads to continue processing without waiting for the completion of credit-card processing; in practice using the RPC to emulate the usual messaging middleware asynchronous communication behavior. But if the Web server sends an asynchronous credit-card processing request, it cannot return an “order processed” message to the user; it would have to return an “order enqueued” message. This would be the situation if you had used messaging middleware. So asynchronous messaging helps process more parallel requests — though usually at the expense of reducing the value of the response.
Besides efficiency and control situations, where messaging is a valuable alternative, there are situations in which it is the only possibility because of the different communication paradigms it can support — namely broadcasting, multicasting and publish/ subscribe communication. And whereas companies are extending the RPC infrastructure to also support some of these forms of communication, in the end, messaging middleware can support them much more naturally and effectively.
Communication models
Messaging middleware really excels in delivering information according to a number of communication models. In addition, we have seen that the great value of messaging middleware is the ease it affords users to change the topology and behavior of the communication channels, as well as the consequent ease of integrating large systems by manipulating the message communication rather than the business logic.
The main communication models provided by messaging middleware are point-to-point message delivery, topic-based or publish/subscribe message delivery, broadcast delivery and multicast delivery.
Point-to-point message delivery is the most used for transaction processing; after all, in most cases you want to make sure your transaction request goes directly to its processing destination.
Point-to-point messaging and HTTP
While messaging middleware also excels in point-to-point delivery, the simple though synchronous HTTP protocol is the real winner in inter-enterprise point-to-point message delivery, not because of any great features, but because it is everywhere and is also allowed through firewalls because it is used in Web interactions. Messaging middleware vendors have recently tried to reclaim the space by providing message delivery over HTTP (or, if security is being used, HTTPS).
Topic-based communication delivers each message to an undefined and possibly changing number of destination queues. Each destination queue is built when a process registers to receive messages about or subscribes to the topic. The destination queues may be created persistently, receiving messages even if the interested process is no longer running, expecting it to pick its messages at a later time. As one can imagine, topic-based delivery is useful for integrating enterprise systems and extending their functionality. Processes can register dynamically to audit, monitor, log or otherwise post-process the messages to add functionality.
Messaging middleware can also provide broadcast and multicast delivery services. These services are mostly access points to the underlying network services with the same name. Because of their underlying implementation they are inflexible; most of their value is in their execution speed and their ability to handle large amounts of data and destinations. Because of such efficiencies, broadcast and multicast are routinely used for the delivery of financial information — more specifically real-time market data — often in combination with topic-based delivery (the ticker-plant at the front-end of a data feed). It is not a coincidence that Tibco, the market leader in providing messaging middleware with broadcast delivery, has gained such a wide acceptance as the carrier of market data.
A look at security
The lack of a direct connection between the message source and destination (even point-to-point message delivery goes through the message queues) has some interesting effects on security, as most secure communication models rely on the establishment of one-to-one communication channels. The most common way to achieve data protection requires the creation of a direct and protected communication channel between the data source and the destination, which goes against the first principles of messaging middleware (the message destination is often dynamically determined by a num-ber of runtime rules and events). So what becomes of the usual authentication and authorization models?
This is where messaging middleware usually falls short on delivery. Currently, the only easily understandable security model considers the messaging infrastructure (queues and routing functionality) part of the Trusted Computing Base. In simple terms, this means that the users will trust that the machines handling a message between the source and the destination will not tamper with it or unduly disclose it.
In some cases this is acceptable, but in many cases it is not; then the burden of communicating securely often falls on the application or the custom logic. Some middleware products go the extra mile trying to make available security services befitting the messaging delivery models. Sadly, the inherent difficulty of the task, a lack of standards and the difficulty in communicating complex security models hinder these efforts.
Message brokering
Messaging middleware can offer more than primitives for message delivery. In the past few years, many middleware products have started to provide higher level services that we will cumulatively call message brokering. These services allow sophisticated custom logic to run co-located with the middleware and to examine, route, filter and modify messages according to content or message envelope attributes. In practice, message brokering can be exploited to the point where a substantial part of a business app will be contained in the middleware’s nodes and the global communication patterns will be defined by the local behavior at the nodes.
In the past, messaging middleware required the use of proprietary message definitions, so that it could look not only in the message envelope but also into the message content formats — and could possibly transform the messages in transit. Because this required a specific product focus, vendors would either focus on the message delivery or the message-brokering facilities.
The acceptance of eXtensible Markup Language (XML) has changed things dramatically. It has allowed any messaging product to easily provide message-brokering functionality for XML-formatted messages. Such facilities can be put together easily with vendor-provided or open source tools.
Without a doubt, messaging products will make increasing use of XML and provide message filtering and content-based routing. In general, message-brokering facilities provide an excellent platform for integrating legacy and new systems, as long as one can easily describe business flows in terms of event-driven logic (otherwise, we would rather recommend developing a solution using distributed components).
This approach to solving business problems using routing, filtering and transformation logic in the messaging middleware is targeted by EAI products.
EAI: the latest evolution
Message brokering is a core technology for EAI products. But EAI is not as concerned with the communication of messages between applications as it is with the definition of enterprise message dictionaries, the definition and execution of enterprise message transformation rules (mapping between enterprise and system data representation), and the definition of business processes in terms of message exchanges and their appropriate execution.
EAI products add to message-brokering facilities the tools required to support such concerns; they also allow for the easy sharing and exchange of enterprise data, and the chaining together of business processes already defined at the enterprise level or as point solutions to provide cohesive sets of business functionality within and between organizations.
Usually the functionality provided by EAI products is delivered via a set of tools to access and manipulate one or more repositories distributed across a small number of message-brokering hubs and visible throughout the enterprise.
The product landscape
A small set of products has so far dominated the market — until now. The fact that messaging middleware was not until recently part of a standard computing platform, together with the lack of non-proprietary interfaces, has kept the field to a few established players. Currently, the most deployed messaging middleware products are probably IBM’s MQSeries, Microsoft’s MSMQ and, in the financial industry, Tibco’s messaging products.
The Java Messaging Service specification has changed things somewhat by defining a standard set of services and a standard API. A number of vendors have put a stake in the ground and brought to market viable JMS implementations. In turn, the availability of an independent service definition and API is reducing the lock-in factor and making users more confident of what they get. However, when standards are defined, products tend to become a commodity. We may see a consolidation of JMS-based products soon.
We have tried to give some shape to the messaging middleware field in terms of functionality and terminology. But it is still a wild landscape with very little standardization. Messaging middleware is definitely a great platform for building distributed systems — even considering its advantages and shortcomings. Large systems are often built with both RPC middleware and messaging. One provides ease of use and transparency; the other flexibility, extensibility and complex communication models.
The challenge is to design architectures that take advantage of both without being swayed by technical religion.
About the Author
Max P. Grasso is chief technology officer, and Ed Lyons and Jonathan Venezian are senior technologists at NetNumina Solutions Inc., a Boston-based e-business solutions provider.