Sometime I find theoretical learning tough for new technologies. As a developer it is easy to learn if things are explained with the help of diagrams and code. I am going to start a blog-series in the view of a developer, where I will be start blogging on microservices from theory to practical. Today is our first blog post of this series where we will start with the theory around microservices.
From the early days of having tiers and layers being represented interchangeably and mostly being the same, we have come a long way to the world of Microservices. As a software developer, I am not able to shake off the contentment I have just to see my code neatly stacked across the three layers lovingly referred to as Presentation layer, Business layer and the Database layer. The application architecture we are talking about is referred as Monolithic architecture. Depending on the level of our prowess with OOPs we would employ classes, interfaces and shared libraries to keep the code manageable.
There wasn't anything wrong with the approach. However there wasn't humongous amount of internet traffic or expectation of lightning speed responses to deal with either. So after employing the best of patterns and spending days of refactoring it was becoming apparent that it wasn't good enough to handle all enterprise applications. Before we move on to Microservices and Azure let's see what are the challenges with Monolithic architecture.
Monolithic Architecture Limitations
Let's quickly see what are the factors affecting the Monolithic architecture requiring a more modern architecture. I will try to list them here in the sequence of importance in my experience:
- System Failure - irrespective of problem in the smallest part of the application, the whole system could fail.
- Code Complexity - despite the best of efforts while employing all best coding practices the code base could grow up to be huge and complex. Any new person coming in might have a learning curve which is not entirely suitable to the immediate response needs.
- Expensive Changes - with the growing code base and inter-module dependency it is only a matter of time that making changes becomes painstakingly slow to code and even more so when deploying or testing.
- Technology Adoption - above points coupled with lack of possibility to adapt new technology results in only even higher turnaround time which is not suitable in order to changing market demands resulting in a slower response to market needs.
- Scalability - could only be achieved at the whole application level and not just a component/part of it. This mean - that you will be investing for the sections of the application which don't need it or won't benefit from it resulting in a cost overhead.
- Continuous Deployment - will become more challenging with every growth in application size/functionality, eventually becoming impossible to be deployed frequently.
Monolithic Architecture Benefits
- Simple Design - makes it easier to develop the application at least in the initial stages.
- Simple to Test - by virtue of the whole application at one place the testing was simpler with not too many scenarios involving communication across boundaries. It is important to note here that testing is simple but not inexpensive - since the entire application is to be tested.
- Faster Communication - with all components residing and operating within the same process [mostly].
- Easy Monitoring - both health and state is easier and doesn't impact design and investment much. Do keep this in mind as monitoring would be a requirement that must be applied from the beginning when dealing with Microservices.
- Scalability - similar to the testing point above, it is not cost effective but just throwing additional instances behind the load balancer would get you started.
So what are Microservices really. There are plethora of definitions and opinions around the related definition. As a developer I define microservices as
an architectural style and it structures an application with different loosely coupled services. This also enabled CI, CD and is not limited to technology.
We will discuss the attributes of Microservices shortly. However in my opinion it is a set of practices and disciplines along with these attribute based development, that creates a true Microservice architecture. Let's first see what the core attributes are:
- Single/Isolated Functionality - don't try to achieve too much with in a single Microservice. Instead, design it for one reason only and do that well. This means that the design should try and avoid any dependency on any other part of the functionality
This part is extremely important in my opinion as it lays the basis for the rest of the attributes. This would require a separate discussion altogether. We will cover it in another discussion.
- Isolated Data & State - each service owns its data and its state. It does not share ownership for the same with any other application or its part.
- Independent Deployment - is a cumulative effect of both the points above. This also helps you with the continuous deployment as well.
- Technology Adoption - is easier with first two points taken care of. Since it would not have an impact on any of the existing modules. The beauty here lies in the fact that you could have two different versions of a Microservice in two different technologies. Extremely beneficial.
- Consistency and Resiliency - has to be impeccable. If you can't rely on a service to return within a speculated period or rely on it to be always available, then the whole purpose of it is lost.
We have to understand that this is not just another fad or forced change. This is a natural and gradual transition in the way we develop application while responding over time to the change in sheer size of the applications or the volume of traffic these applications are meant to handle.
Having the Microservices approach has some challenges as well. Here is the flip side of the coin for you. And before you decide that any of these is a big deterrent, let me assure you that if you already reading about Monolithic alternatives, you have grown beyond the capabilities of Monolithic. So it is a good idea to adopt it in the best possible way.
Microservices is paradigm shift in my opinion. It is more so at the organization level as well. We must understand this in order to adopt and benefit from Microservices. Presently even the organization hierarchies like QA Group and Deployment Team are focused around the Monolithic applications itself.
Let's discuss the changes required when you adopting Microservices:
- Inter Service Communication - becomes one of the pivot points affecting the overall design.
- Testing - has to consider a fabric of Microservices when writing scenarios.
- Continuous Deployment - should become part of the adoption from early on. As the application grows in the number of Microservices part of it, not having CD could quickly spiral out of hands. This is also required for Testing.
- Development Tools - more suitable for Monolithic design presently and would advance over time.
- Distributed Transactions and Reporting - needs to be well planned for. As nothing stops a Microservice from implementing Monitoring and Logging in different ways. However the entire fabric must agree and support a common minimum denominator.
In this blog post I tried to layout the foundation of our series by discussing various benefits and downfalls of Monolithic Architecture and then moved on to see the attributes we look for in Microservices.