The Ten Commandments of Microservices
Microservices mark the beginning of the new era in distributed computing.
With the emergence of containers, the unit of deployment gradually started to shift from away from the VM models. Linux container technologies, such as LXC, Docker, runC and rkt, make it possible to run multiple containers within the same VM, allowing DevOps to package each app component or app module in a dedicated container. Each container has everything—from the OS to the runtime, framework and code—the component needs to run as a standalone unit.
The composition of these containers can logically form an application. The focus of an application becomes orchestrating multiple containers to achieve the desired output.
Yet, there is a misconception that moving a traditional, monolithic application to containers automatically turns the monolithic system into a microservice. Containerization doesn’t instantly transform an app to a microservices-based application.
The best way to understand this concept is to think of virtualization and cloud. During the initial days of IaaS, many CIOs claimed they were running a private cloud; but, in reality, they were only implementing virtualization. Likewise, while microservices may use containerization, not every containerized application is a microservice.
Here are some additional aspects the architect should consider when moving to microservices:
1. Clean Separation of Stateless and Stateful Services
Applications composed of microservices contain both stateless and stateful services. It is important to understand the constraints and limitations of implementing stateful services. If a service relies on the state, it should be separated into a dedicated container that’s easily accessible.
One of the key advantages of microservices is the ability to scale rapidly. Like other distributed computing architectures, microservices scale better when they are stateless. Within seconds, multiple containers can be launched across multiple hosts. Each container running the service is autonomous and doesn’t acknowledge the presence of other services. This makes it possible to precisely scale the required service instead of scaling the VMs. For this pattern to work seamlessly, services should be stateless. Containers are ephemeral and thus, become an ideal choice for microservices.
A microservices-based application may contain stateful services in the form of a relational database management system (RDBMS), NoSQL databases, and file systems. They are packaged as containers with unique attributes. Typically, stateful services offload persistence to the host, which makes it difficult to port containers from one host to another. Technologies, such as Flocker and Docker volume plugins, address this problem by creating a separate persistence layer that’s not host-dependent.
Typically, stateful services offload persistence to the host or use highly available cloud data stores to provide a persistence layer. Both approaches introduce complications: offloading to the host makes it difficult to port containers from one host to another, and highly available data stores trade consistency for availability, meaning that we have to design for eventual consistency in our data model.
Technologies, such as Flocker, help address the host portability problem by creating a separate persistence layer that’s not host-dependent. The new cloud datastores, such as Redis, Cassandra, and IBM’s Cloudant, maximize availability with minimal delay on consistency.
As container technologies evolve, it will become easier to tackle the stateful services problem.
2. Do Not Share Libraries or SDKs
The premise of microservices is based on autonomous and fine-grained units of code that do one thing and one thing only. This is closely aligned with the principle of “don’t repeat yourself” (DRY), which states that every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
Every service is a self-contained unit of OS, runtime, framework, third-party libraries and code. When one or more containers rely on the same library, it may be tempting to share the dependencies by centrally configuring them on the host. This model introduces complexities in the long run. It not only it brings host affinity, but also breaks the CI/CD pipeline. Upgrading the library or SDK might end up breaking a service. Each service should be treated entirely independent of others.
In some scenarios, the commonly used libraries and SDKs can be moved to a dedicated service that can be managed independently, making the service immutable.
Read the entire article at The New Stack
Janakiram MSV is an analyst, advisor, and architect. Follow him on Twitter, Facebook and LinkedIn.
Good Article Janakiram. Do you have view on orchestration or choreography of Microservices in a Business Process that is easy to change?
Nice article Janakiram. Would you be able to share thoughts around this question? - Hosting two similar business units as two separate micro service as against grouping them as one and by doing so, not repeat the same service layer implementation for both?