Hopefully we can all agree that “loose coupling” is a good thing when it comes to software design. The goal is to build software systems that are made up of parts that have the least possible dependence on each other. The benefits are obvious, we can change, remove or add parts with minimal impact to the rest of the application.
While the design principle of “loose coupling” is applicable all the way from overall system architecture to the lowest level class design, in this blog post, we will focus on coupling between high level sub-systems of an application. We will also focus on message exchange patterns (such as publish-subscribe, temporal decoupling and load balancing) and persistence patterns such (schema less and NoSQL document based store). My objective is to demonstrate how these well-known patterns can be realized using Microsoft Azure Platform based services such as Microsoft Azure Service Bus and MongoDB.
Even though we are talking about Microsoft Azure based applications, the concepts we discuss below apply to on-premises as well – given that Microsoft Azure Service Bus has an on-premises equivalent known as Microsoft Service Bus and it makes no difference whether MongoDB is installed on-premises or in the cloud.
Let us assume that we are building a website that provides insurance quotes to its users. This website is itself an e-commerce aggregator that in turn relies on one or more underwriters to provide quotes based on the data submitted by the user. You can quickly see why loose coupling would be good for an application such as this. We want the ability to dynamically add/remove underwriting partners. We also want a robust setup for interaction between the website and the underwriting partners so that a failure of one of the partners does not adversely impact the overall application. Certainly the ability to scale with load is going to be important for an e-commerce aggregator. Additionally, each underwriting partner may have a slightly different view of the data fields that make up a quote. So we want our persistence store to support dynamic schema. Finally, we may want to add new insurance products (home, cycle or cyber) in the future.
The following diagram depicts the high level architecture of our e-commerce aggregator application:
The website (Store Front) is implemented using Azure Web Sites. The store front website stores the incoming quote request into a MongoDB based store for quotes. It also places the incoming quote request with a Windows Service Bus topic. In contrast to a queue where each message is processed by a single consumer, topics and subscriptions provide a one-to-many form of communication. Turns out that this is exactly the form of communication we need for our underwriting partners, who each should receive a copy of the incoming quote. Once the incoming quote has been processed, the underwriting partner will post a direct message back to the store front. The store front in turn will store the quote response(s) in the quotes database. As you can see, in addition to the one-to-many form of communication, Azure Service Bus topics and subscription also offers us temporal decoupling and filtering. This means that underwriters don’t have to process the incoming quote requests immediately after their arrival. Filtering will come in handy when we support additional insurance products in the future by making it possible for underwriters to subscribe to only a subset of incoming quote requests.
MongoDB is a NoSQL database that allows us to store quote data using a flexible schema – which means that the data fields that make up a quote request and response(s) can be stored as a “document” (equivalent to a RDBMS record) within a MongoDB collection (equivalent to a RDBMS table). Since the documents within a collection can have different fields, we can easily accommodate difference in quote responses. The flexible schema feature really shines when we want to add new insurance products where there are substantial variations between quote request and responses. This flexibility allows us to keep a single embedded document (i.e. quote request and responses embedded within a single document)) leading to better read performance and the ability to retrieve the all related data in a single database operation.
Here are some design considerations when building loosely coupled applications on the Microsoft Azure platform:
- Based on the desired message exchange pattern determine if Microsoft Azure Store Queue or Microsoft Azure Service Bus meets your needs. Review this MSDN article for detailed guidance.
- Determine what the parameters for temporal decoupling will be. For instance, what is the expected time-to-live for a quote request?
- Determine the filter rules for a topic on a per-subscription basis.
- If you decide to go with NoSQL database, understand the atomicity requirements. MongoDB operations are atomic at a document level. In other words, no single write operation can change more than one document. Additionally, consider the indexing the sharding options. Finally, MongoDB includes an aggregation framework that can examine and perform computations on datasets.
Microsoft Azure platform offers various building blocks for building loosely coupled applications. This includes various message exchange constructs, brokered communication and schema-less persistence.