Software embracing a microkernel architecture has been happening for the last 20 years, yet the great aspects of this particular architecture are too often undermined and not considered when working on a new project. There are various reasons for this, history behind it with poor experiences, but there has also been a lot of lessons learned . So what can one benefit from a microkernel architecture?
In the last two decades, a lot of changes happened in the world of software and Internet has revolutionized quite a few trends. Microkernel architecture used to be adopted for operating system type of implementations pretty much exclusively. I remember about ChorusOS, a Unix variant and first-generation microkernel OS developed in the early 90's which was targeted at high-availability applications in the telecommunications space. Chorus was truly innovative back then and like Mach, another first generation microkernel OS implementation, suffered performance issues due to message processing between the kernel and user spaces (no sharing of address spaces). Minix, another well-known unix-like OS based on a microkernel architecture was created by Andrew S. Tanenbaum in 1987 and influenced the development of Linux although Linus Torvalds went with a monolithic kernel architecture instead.
There has been quite a few debates regarding the benefits and tradeoffs of a microkernel architecture versus a monolithic one. Most Unix operating systems are based on the last one, with no messaging between parts of the system and an easier (and controlled) access between the kernel and user spaces. A microkernel-based implementation typically grants the software with added modularity and flexibility due to the abstraction and extra independency (clear boundaries) between the various modules / parts of a system.
I stated earlier that trends had changed in the last 20 years and although it may sound like stating the obvious, what I really meant to say is that software architectures do evolve due to other factors such as hardware, markets and new requirements. Today one can see a lot more software implementations based on a microkernel architecture, due to an increase demand and new requirements motivating that choice. Hardware (e.g. memory, CPU) has gotten a lot faster and cheaper, there is a lot of hardware environments to port to, the internet and its fast moving pace has increased the demand for more dynamic and flexible software.
Multi-threaded server applications are a lot more popular these days and the overhead of a microkernel-based implementation is no longer an issue when it comes to interactions between various modules involved in a particular processing operation. It used to be true for the most part, when IPC mechanisms had to be used to relay messages between modules running as part of different processes.
A microkernel architecture could be summarized to a "highly modular collection of application-neutral abstractions upon which can be built robust, flexible and dynamic applications" and brings the following and non-exclusive benefits to software implementations:
- Better footprint management
- Easier development, unit testing, maintenance and portability
The modularity, flexibility and extensibility aspects are what I would consider the most important ones of a microkernel-based implementation. A highly modular architecture allows protocols to be separated from their implementations as well as maintaining a level of independence between the various modules and components / services (enforcement of boundaries) of the system. Flexibility grants you with dynamic loading and unloading of modules and extensibility gives the developers means to extend the current system with new protocol or schemes implementations.
Footprint management can be an important issue in certain environments and the ability to remove unnecessary components as part of your application can help reducing the footprint significantly.
Modules can be developed and unit tested independently of each others and portability is usually easier to handle as non portable logic can be placed at the kernel level directly and not mixed with non-kernel components.
As far as potential performance improvements, I think this is very debatable unless one is dealing with a single-threaded monolithic implementation and in this case it would be slower on SMP machines obviously. I'm a big fan of multi-threaded implementations versus multi-process ones and in this case both architectures would run better on multi-core systems.
Microkernel-based architecture has also reached the world of database systems and most recently, Drizzle, a fork of the MySQL core engine has been announced and is supposedly aimed at Web and Cloud applications. This confirms the need for more modular and flexible implementations at the database management system level.
Microkernels and the likes in Java land
The Java platform and more specifically the language, facilitates the development of microkernel-based implementations. The object-oriented aspect of Java allows abstractions via published interfaces to be defined for the various parts to be implemented. In other words, this enables a clear separation between the protocol various implementations. Java dynamic class loading also allows modules to be loaded on the fly as needed.
To name a few Java applications and frameworks which have adopted a microkernel-based architecture:
- GlassFish V3 has adopted HK2, the Hundred Kilobytes Kernel, with a module subsystem and component model
on top of OSGI
For an example of a Spring DM application leveraging OSGI dynamic module system and separation of application logic into modules, I recommend reading this article.
Apache Derby which can also run as an OSGI bundle (since 2005) is used in this example as well.
There is also growing interest in the cloud computing arena with having a more modular, flexible and extensible Apache Hadoop. Being able to plug-in a query language of choice on top of Hadoop's huge datasets is a very attractive value-proposition indeed.
Apache Derby Case Study: How to benefit from a Microkernel architecture
Apache Derby / Java DB has been supporting a highly modular architecture since its inception in 1997 with its first release as part of Cloudscape. Derby's system is composed of a monitor, acting as a kernel of its own, booting and shutting down services as well as discovering appropriate modules to load for a particular service. As an example, different modules can be loaded during boot-up based on the environment such as the JVM version. Modules themselves can also require other modules to be loaded in the environment.
Derby already supports pluggable authentication schemes as well as pluggable raw storages via its module-based subsystem. It promotes a clean separation between the SQL and Store layers which favors the implementation and pluggability of different types of storages. For instance, one could envision a GRAPH storage for Derby to enable a graph-based data model to be accessed via Derby's relational engine. There is already some implementation of an in-memory storage and even a store-less storage type to test Derby's layers separation and submit queries against non-database objects.
The extra benefit of having a clear separation between a protocol and its implementation allows other projects to re-use parts of the system and contribute back to the open source community. For instance, several project have expressed their interest in integrating Derby's raw B-Tree storage as it has proven to be robust over 10 years and has an active open source community.
There are already on-going efforts and proposals to make Derby more flexible and reduce dependencies between modules of the store layer and have a cleaner pluggable storage implementation. When this modular architecture got implemented 10 years ago, there was little demand for specialized and pluggable storage. This has changed with new types of data models and requirements for web applications and cloud computing, translating into innovations at the data management level.
The good news for Derby is that it has already gotten the proper foundations in place to go the extra mile and have a clean microkernel architecture. This would not only benefit the store layer but also other parts of the engine, such as the SQL compiler (parsing and execution plan generation) and the access layer, residing above the store. For instance, one could imagine having Derby's SQL layer plugged-in on top of Hadoop, as an extension to be able to run SQL queries against MapReduce datasets.
Software implementations which are supporting a microkernel architecture inherit highly modular and flexible characteristics. The performance gap between a monolithic and microkernel architecture is no longer much of an issue, especially in a multi-threaded environment where messaging is done via local interfaces without requiring the use of IPC mechanisms.
The dynamic nature of web applications and requirements to constantly adapt to new standards and protocols will continue to promote this architecture. OSGI has already showed some path and additional web frameworks have become compliant.
Derby with its highly-modular architecture excels in an embedded server mode configuration and is a natural database storage of choice for the Java platform and microkernel-based implementations in the middle-tier.