High Availability through Modularity

Modularity: A few simple steps that will take the sting out of an enterprise application update.

Many enterprise systems, for one reason or another, need to be available around the clock. Applying software updates to such systems is usually even more challenging than in systems that do allow some down time e.g. in the middle of the night on a Sunday.

One proven technique is to build the application as a collection of loosely coupled, well-defined modules and run those modules in a dynamic system that allows them to be installed, updated and removed without stopping the system. Loosely coupled means that the individual bundles have no visibility to the internal workings of the other modules but only to what is defined in the interfaces, or the contract. For example, imagine a stockPrint module that prints the stock price for certain companies. It obtains that stockprice from a stockService module, but how that stockService module gets that information is irrelevant. As long as we add that stockService module to our system, our stockPrint module is happy, and functional. Out stockPrint module can specify if it requires 0, 1 or many stockService modules before it can start. Zero might seem strange, but this is the crux in a dynamic system. It allows our module to start but it will not be able to print current stock prices but maybe it has some other functionality like printing previously received stock prices and as soon as a stockService becomes avalable it will start to print the current stock prices as well. It is easy to see that now the stockService module can be updated individually while the other modules continue to run, albeit maybe with temporary limited functionality if it needs access to the stock prices.

What about new functionality?

How to introduce new funtionality in a running system. This is where the module versioning system comes into place. Each module has a version number and if a module requires or depends on another module it not only specifies the services required (e.g. stockService) but also the minimum version of that stockService. Let’s say that stockService-1.0 only provides prices for stocks traded on the NYSE. Now stockService-2.0 becomes available which also provides the quotes for the Amsterdam (AMX) and Frankfurt (DAX) stock exchanges. As long as the new stockService-2.0 is backwards compatible, meaning it also supports the stockService-1.0 function, our printStock-1.0 module is perfectly happy since since the ‘old’ contract is satisfied. Now we can dynamically update our stockPrint module to version 2.0 which requires the stockService-2.0. It is clear that this requires some thought and planning, especially when many modules are involved, but all this can be done without taking the system down.

The modularity described above is available in a framework called OSGi and has been around for 20 years now. OSGi is a specification and there are several commercial and open source implementations of this specification. Eclipse Equinox, Apache Felix, ProSyst and Knoplerfish are the most popular. There are several OSGi based runtime containers that take the burden out of the development of the infrastructure and let the developer focus on the application instead.

Seecago has successfully used OSGi frameworks for different enterprise level applications and we have no reason to believe that will change any time soon.