Typically, a Service Oriented Architecture (SOA) system has multiple and different services receiving the same type of messages. For example, a purchase order can trigger either creation or modification of an order, which may be handled by different business flows connecting to different back-end systems. Ideally, you provide to the outside world a coarse grain service for order creation, and another coarse grain service for order modification, etc, so that an edge application, such as an order capturing application, can call these coarse grain services accordingly.
But the challenges come if the only interfaces to the external edge application or applications are message queues. Immediately it begs the question: should I use the same queue or different queues for these messages, which are of the same type but intended for different services? What are the pros and cons? What are the technical challenges and best practices for each approach?
This blog post is trying to tackle these challenges. There is not a single solution that fits all situations. Rather, we will examine the pros and cons of each solution from different angles.
The first angle to look at is of course the edge application that initiates the message.
Some edge application can only communicate to a single queue for various types of business transactions. In this situation you have no choice but to opt for the single queue approach. Fortunately, the message headers or content typically contains the routing information, so that the messages can be routed to the matching services downstream.
When you have multiple services, the first thing you want to make sure is probably that each service only receives the messages that belongs to it and no cross-routing happens.
In the dedicated-queue approach, since each service uses its own message adapter to consume messages from its queue, there is no need to route the messages from the queues to the services.
In contrast, the shared-queue approach requires the system to have the ability to route the messages to the proper services that they belong to. The routing logic has to be based on the incoming messages themselves. If there is no routing information embedded in the messages, you can not use the shared-queue approach.
Please note that mid process receive via a message adapter faces the same routing challenge as the initial receive. Despite of a common misunderstanding, the correlation mechanism for mid process receive can not help the adapter to route the messages to the correct composite.
From the perspective of operational management complexity, the shared-queue approach has advantage over the dedicated-queue approach. Obviously, you need to manage multiple queues in a dedicated-queue approach, compared to managing single queue in a shared-queue approach. This is usually the main reason why people choose shared-queue instead of dedicated-queue.
To ease the complexity of managing dedicated-queues, you may want to name the queues to reflect the names of the services they belong to.
Both the shared-queue or dedicated-queue approaches demand you to answer the same question: should you run the message queue(s) in the same servers as the services or in their own servers? I would recommend to run the message queue or queues in server cluster different from the service, so that queues and services will not compete with each other for system resources. This separation also helps with the diagnosis of performance and high-availability issues.
From the perspective of separation of concerns, the dedicated queue approach has advantages over the shared queue approach.
These concerns we could separate by using dedicated-queue include:
Now let's look into each of them, to see how the dedicated-queue approach addresses the separation of concerns differently from the shared-queue approach.
First is performance profile and requirements. Some services may have much higher transaction volumes than others. Some services may involve much larger message size. The performance management of the message queues are very different between these performance profiles and requirements. By separating the queues, each queue can be managed individually with minimum impact to others.
Different high availability requirements also lead to different configuration of message queues. Some services are more mission critical than others therefore need to be highly available, which requires whole server migration accompanied by disaster recovery strategies. Others may be able to sustain more down time. The requirements for the HA infrastructure underlying the message queues for these services could be very different.
When services share the same message queue but have different release cycles, you need to consider whether the software release cycles of services can interfere with each other.
In the dedicated-queue approach, adding a new service requires the creation of a new queue, but will not cause interruption of the existing services. The same applies to renewing/redeploying an existing service.
In the shared-queue approach, adding a new service or renewing an existing service could cause interruption to the existing services. These interruptions could happen in the following ways:
By now, you should be equipped with a framework to evaluate the pros and cons of using dedicated-queue and shared-queue approach, and the best practices for each approach.