This is the second in a three-part series on multi-tenancy within Windows Azure applications. Here is a breakdown of the topics for these posts.
Post 2 – Combinations of Instances and Tenancy
Post 3 – Tenant Strategy and Business Application
Part 2 – Combinations of Instances and Tenancy
SIST (Single-Instance, Single-Tenant) Architecture
SIST is the simplest of designs since there is only one tenant with their own dedicated instance. It is typically however the most expensive option since all costs are 100% the responsibility of the one tenant. Cost savings via shared commuting infrastructure is thus a non-entity in the SIST case.
Applying the analogy from our previous commuting example means one rider has their own dedicated train getting to work. Since the driver has their own train they can leave their own personal belongings in the car between days of driving and not worry about anyone having access to it. Any member of their family can use it, but only members of their family.
Applying it to your Windows Azure application would mean one customer of your application with their own dedicated Azure instance. Application state within the process is dedicated to that one application and no other companies can have access to it.
SIMT (Single-Instance, Multi-Tenant) Architecture
SIMT adds complexity to the SIST model by allowing more than one tenant to concurrently execute within one instance. This design is the first step in realizing cost savings from sharing resources found in that instance between customers.
The commuting example applied here is that of a single train where many riders from different companies share the cost of using that one train. However unlike SIST, there are times of the day when the seats are hard to find and a rider may need to wait for one to come open. There is overhead incurred to load and unload many riders from different companies on and off the train. Since the train is a common shared entity if a rider leaves their personal belongings in the train between rides there is a very good chance it will not be there the next day. Or it will be accessed by someone from a rival company.
Applying this analogy to your SIMT Windows Azure application would mean at times a customer may have to share and wait for resources during busy times. The overhead of context switching occurs since the CPU will switch between processing threads specific to that company. Memory and CPU can be taken up by other tenants in the VM process space. If state is used it must protected and managed so that each customer’s state makes it appear to them they are running in a dedicated SIST environment.
MIST (Multi-Instance, Single-Tenant) Architecture
Moving from single-instance to multi-instance the MIST configuration has multiple instances of the application with one tenant per dedicated instance. This is really SIST but with more than one instance of the dedicated application per customer.
Applying our commuting example there is still only one customer per one dedicated train but there are now multiple trains for that customer. Like SIST this does not translate into any shared costs savings for the rider. But since there are now multiple trains, each with one customer, there is now the potential for more money to be made by the railroad company. This is because it can now extend dedicated train service to many riders of that company.
Just like SIST, within an MIST Windows Azure application a customer should not have to share or wait for process resources. Each customer of the application has a dedicated Azure instance space each with their own copy of the application. This could be an issue with respect to upgrades since each individual instance will need to have its application updated when an update occurs. Application state within the process is dedicated to that one customer so no other customers can have access to it.
Since MIST is an upgrade over SIST there is the added complexity of having multiple applications possibly accessing the same shared resources outside of the dedicated instance space. That could mean accessing a shared Azure queue or table in SQL Azure. So while you can make intra-process assumptions on state, data, and processing based upon one dedicated customer per process, you need to be aware of inter-process operations where customers need to process resources outside of their dedicated instance space.
MIMT (Multi-Instance, Multi-Tenant) Architecture
MIMT rounds out the multi-tenant configurations by allowing multiple tenants to run in multiple application instances. It offers benefits with “potential” increased scalability and availability. I use quotes around the word “potential” because contrary to the popular misconception bigger is not always better. One cannot always assume that the MIMT architecture is the ultimate performance choice. While MIMT allows the best opportunity for optimized performance, too many cooks can spoil the broth.
The applied commuting analogy we are using in this case would mean multiple trains carrying multiple riders from multiple companies. This has the same issues as a shared single train in the SIMT case. Additionally there is the added complexity of different train tracks and thus different routes. This can be a subtle point of confusion if not managed correctly and can negate the benefit of having multiple trains going to the same end point.
For example suppose a family wants to travel to a certain destination and coming from different locations after work – sister from college, brother from high school, mom from her work, and dad from his work location. If their goal is to meet for dinner at a certain stop along the route they need to coordinate the times they leave and arrive. This ensures they optimize their travel cost and time to arrive as close together as possible. It would not be ideal if dad arrived an hour before everyone and had to wait for them all to show up over staggered times. Or if brother took a train in the other direction he would go hungry. Design and coordination of activities is important in making this a successful dinner trip. If done right, it is more efficient if they all take different trains to the same endpoint (SIMT) and don’t have to all drive a car (SIST) to a single train station to ride together. If not done optimally with different trains from different locations it can actually take longer than all driving the car to one train.
Applying this analogy to a MIMT Windows Azure application should be a fairly simple transition in your mind. Like an SIMT Windows Azure application may have to wait for resource, incur context switching overhead, and have to carefully manage individual state. There is an additional complexity involved that can either improve on the SIMT situation or actually end up with worse performance than SIMT. This is the ‘hard’ part of MIMT applications and is really application dependent in nature.
MIMT is an architecture that lends itself to use concurrency-based architecture patterns (Event Based Synchronous, Lock, Guarded Suspension, Concurrent Data Access, etc.). This allows you to coordinate and isolated work across multiple instances or across different threads in the same instance. Client 2 in the diagram below has two threads of execution in the third Azure Web instance and one thread in both the second and fourth Azure Web instances. The code for Client 2 needs to manage that complex concurrency.
Sounds complex? Well that’s because it can be. So here are some guidelines for coordinating multiple clients across your multi-tenant Azure application:
- Synchronize access to all persistent and state data
- Avoid long periods of locking or blocking while accessing resources
- Avoid state as much as possible. Being stateless allows code to run properly on any thread on any server.
If you must have state, manage state correctly and in a central location that all threads can access regardless of what server they are running (Windows Server AppFabric Cache or a central database state server).
Minimize serialization and try to avoid deadlock situations
Carefully ensure your processing is optimized over not only multiple threads but over multiple servers.
Ensure none of your processing makes any assumptions about which Azure instance or thread any of your code running.
Don’t assume specific threads or instances will be accessing state or persistent data from across multiple Azure instances.
The above list is not all-inclusive yet it gives you some considerations of which to be aware. It may give you an appreciation of the potential complexity of ensuring your Azure MIMT app runs optimally across many VMs for many customers. Your code can run on any thread on any VM at any given time. Code must be written to be flexible and able to easily transition to any thread on any instance on any VM with the data still maintaining its integrity. Remember my earlier statement that your MIMT app can be more efficient than an SIMT app if done correctly. Or it can actually run slower if not designed correctly.
Various combinations of tenancy can exist throughout the spectrum of instances and tenants at the different application layers. The requirements of your application will be the key factors in these tenancy decisions. Application components and data should properly manage more than one tenant having access to them.
In the next and final post we will look in detail at tenacy strategy and business application.