Advanced Message Queuing Protocol (AMQP) is a tool that has been used to enable many distributed, loosely-connected applications. Like any tool, effective use of Messaging platforms depends on how they are used. Are there problems that naturally lend themselves to a Messaging architecture? Perhaps more importantly, are there problems that discourage Messaging? First, however: why is Messaging a valuable pattern for any software system?
A good analogy to make to a Messaging platform is a piece of audio equipment called a patch bay. By itself, a patch bay is not useful. Its utility lies in connecting other pieces of audio equipment to each other. A patch bay enables a guitarist to hear the bass guitar, but not the horns. It enables the singer to inform all the musicians to take it to the bridge. A patch bay enables mixing all musicians together and amplifying them so that each part can be heard in a large venue. In short, the patch bay enables individual musicians with unique needs to make unique contributions that can combine to sound like a band. Each contribution is important in itself, but the complete song is greater than the sum of its parts.
By extension, most software systems of medium complexity will need to connect individual software components with unique inputs and unique outputs to coordinate them into a workflow. For example, suppose a customer has submitted an Order for processing, which triggers several operations. The raw message is logged for auditing purposes. The Order data is persisted to a store. Payment information is processed, and the accounting system updated accordingly. Providers who can fulfill the Order are notified, perhaps because the provider is familiar to the customer, in the same physical location, or is recommended the Order based on past behavior.
In the Order workflow above, some operations are related and should be grouped in a transaction, such as payment processing and updating the accounting system. But some operations are completely unrelated and could occur in parallel, such as logging and persistence to a store. Some operations have identical inputs, but unique results, such as determining which provider to notify based on the characteristics of the Order. Finally, some operations rely on the outputs of previous operations, such as notifying the appropriate providers above via SMS, email, or OS push notifications. A Messaging platform could be utilized to coordinate these operations to ensure that the Order is fulfilled successfully.
AMQP possesses several features that facilitate connecting and coordinating the operations above. AMQP is Message-oriented, or geared toward communication among distributed systems. Any platform that implements AMQP will expose endpoints to allow other systems to publish messages to it. Those messages may contain routing information to ensure that the messages are published only to the appropriate endpoints. Upon publication, the messages will be assigned an order and may be placed in a Queue for another system to consume. All communication will be reliable: clients that publish messages receive acknowledgment by the platform when messages arrive successfully or not. Finally, Messages may also contain authentication information to secure publication and ensure no malicious clients may publish.
Fulfilling the Order workflow described above may be accomplished by exposing a single endpoint for publishing Order data:
order-input. That endpoint is configured internally to publish to two other endpoints: one from which a logging component consumes (
log-input), and one from which an Order persistence and processing component consumes (
order-process-input). When the Order processing (including payments, accounting, and persistence) has completed, the result is published to an Order Complete endpoint:
order-complete. That endpoint is configured internally to publish to three other endpoints for gathering providers to notify, which subsequently publish to endpoints that create the actual notifications via SMS, email, OS push notifications, etc.
The Order workflow could be fulfilled using the set of endpoints described above, but what are the ramifications of using Messaging? First, each operation is atomic: only one purpose is fulfilled, and no operation is tied to another. The benefits of routed messages are the same as any loosely-coupled design: modifications to one component will not affect the others. Further, because the messages are routed via configuration, the workflow is simple to update. Adding another endpoint to
order-complete to push financial information to a data warehouse does not affect the existing workflow. Finally, because successfully processed messages require acknowledgement by the consumer, a built-in retry mechanism for failed operations exists.
The downsides to using Messaging are subtle. Is coupling persistence, payments, and accounting adequate for the business? Perhaps each operation should be fulfilled by a separate routed endpoint. If they are separated, what happens if one operation fails? Should the Order still be published to the Complete endpoint?
Are individual endpoints to gather providers to notify adequate for the business? One provider may satisfy multiple conditions, but should not be notified for each condition he satisfies, which may suggest coupling the gathering operations. What happens if one operation fails? If the recommendation engine is offline, but the other endpoints are not, is that adequate for the business?
The answers to questions like these are critical when deciding whether a Messaging platform is appropriate for your application. Some art is involved, but the first step is to classify operations as unrelated, or requiring a transaction, or sequential. The next step is to determine whether errors can be ignored or require retrying until successful, and how errors may affect other components.
If your application contains many workflows that involve several of the same operations (such as reusing the notification components for traffic updates) or has frequently changing workflows, a Messaging platform may be appropriate. On the other hand, if your application consists primarily of static or unrelated workflows, it may be difficult to justify the added complexity of setting up and maintaining the platform. Messaging is not difficult to conceptualize, but done poorly can easily introduce as many problems as it is called upon to solve.