Principles Of Microservices: How To Architect A Solution12 min read
- In Blogging
Every enterprise has its own principles.
Principles that takes it towards the goals.
Principles that give birth to practices which are the underlying foundation for all the implementation.
Similarly, Microservices has its own set of principles that helps its implementer to make the correct decision when given multiple options to choose from.
Principles are like guiding markers. It helps to make a better decision, helps to choose better that will take the enterprise closer to its goals.
In this article, I will talk about the Principles Of Microservices. The guidelines which you would want to stick too at all times while designing a microservices architecture for your enterprise.
By any chance, if you have not read my previous article on Microservices then please do. It contains some useful information
The very first principles help you to model your services.
Principle 1 – Model Around Business Domain
The microservices must always be designed around the Business Domain.
Let me explain it to you by talking a little bit about the traditional architecture that enterprises have been following so far.
Traditionally, the enterprises use to follow the 3-tier architecture. This 3-tier architecture consists of a:
- Presentation Layer
- Business Logic Layer
- Data Access Layer
This was a very simple architecture to understand. No doubt about it.
All the presentation logic resided at the presentation layer, all the code that deals with Business Logic of the application resides in the middle layer and the data access part resides in the last layer.
And the flow is unidirectional. The flow always goes from Presentation to Data Access and not vice versa.
It was easier to explain this architecture to someone new joining the enterprise with no industry experience at all. And this helped people to get started quickly. But there were multiple downsides to it.
To Add/Subtract Anything, it requires a change in all the three layers
This is a major drawback.
A single feature addition, as simple as adding a new property to your frontend requires the change in all the three layers.
If we go further back in time when organizations did traditional monoliths, it was usually one team that has to work on all the three layers.
And by three layers I mean 3 different codebases.
One Team – 3 Codebases <- this sounds daunting but it actually worked well at that time.
But not for long.
As the enterprise grew, business ask grew, which intern increased pressure on the developers to develop features faster and reduce the time to market.
Now, this model was preventing the growth of the enterprise and putting pressure on developers.
Apart from this, there were other problems as well.
Developers Mindset Was Geared Towards the Same Tech
As one team dedicatedly work on one codebase, their knowledge and mind were all geared towards that same technology stack.
One may argue that this is better for the developer as he will become the expert of that field. But if you ask me (developer), I would not want to work on the same project for long. It isolates me from all the wonders happening around me.
Knowledge ~ Exploration
Contracts Between Layers Were Assumed to be Valid and Truthful
As there was only one person/team working on all the three codebases, there was no need for contract testing. Every incoming request was assumed to be valid and truthful.
They didn’t give much attention to validation of the incoming data (data coming from other layers) because they are the ones who have coded it. And they are sure what is incoming. So they never felt a need for validation.
Did Not Bother About Chattiness
Since one developer or one team was working on all the different codebases – they didn’t bother about the network payload, performance, load and boundary restrictions.
Thus there was a need for a new model.
And a new model took its place.
Segregation Of Team Across Different Layers
In this new model, each layer was developed by individual teams.
This new model did take the load off the developer and solve some of the earlier problems but as you know – It is always a tradeoff that we make. So, this new model also brought its own share of problems.
Now the problem is this – for a single change, it required coordination between all the three teams. And this prevented rolling out quick changes.
I have kept these diagrams small and simple for the sake of explanation. These layers can go deeper, multiple layers inside each layer and it makes a single change very difficult.
To get rid of this silos, enterprises started looking for a better and more independent architecture.
Not Easy To Explain In Layman Terms
3-tier architecture seems simple enough to explain to a technical person. But it is not straightforward to explain it to a non-tech person.
You see, Business people talk in terms of features and use Business terms. They would not understand a word if you would talk in this technical term and there will be a communication hole in between.
On top of that, a single feature requires 3 different teams to work in collaboration. So there is an overhead of managing the three teams as well.
Both of these drawbacks can be taken care when you model your services around Domain and not around technical layers.
How Does Modelling Around Business Domain Help
The major advantage that you get with Modelling around Business Domain is that it gets easy to explain to others.
For example, take a look at the below image:
This image is fairly easy to demonstrate and understand. Clearly, it shows that each microservice deals with an individual business domain. And how it interacts with each other.
Any non-tech guy will be able to better understand it without much explanation.
Furthermore, each service is owned by one team in its entirety so it is easier to roll out new changes. The intercommunication between the teams is good and fast.
What microservices has done here is that instead of making a horizontal slice, they have made a vertical slice where they are covering each part of every layer. Therefore, these models also fit well with the Agile software development model.
These two are major advantages of designing your microservices around business domains.
And it is the first principles of Microservices.
As the list is exhaustive and huge so instead of waiting for the entire article to complete I plan to update the same as I write about other principles. So if you are interested then make sure to subscribe. I will keep you updated.
Principle 2 – Automation
Deploying a monolith application is a fairly straightforward process. You have everything packaged into one and boom the app is deployed. But with Microservices, it’s a whole another story.
With the increasing number of microservices in an enterprise with their interdependence can make it a complex process and a developer’s life miserable. That is why we need to leverage the technologies that allow us to automate all of this. I’m talking about a culture of automation using CI and CD.
CI became the need of the hour with the advent of microservices architecture.
With CI, the core is to keep everyone in-sync with each other by making sure that the newly checked-in code integrates well with the existing code.
This is done by performing a series of verification steps performed on the newly checked-in code to see if the code compiles successfully, whether the test cases are green and more… If you are not using CI, then working with multiple teams and multiple services is going to be painful and nasty.
Benefits Of Continuous Integration
There are many benefits of Continuous Integration:
- Faster feedback – You can the feedback within minutes whether the code that you have checked-in integrates well with the existing code.
- Code Quality – You can attach Continuous Inspection tool such as SonarQube for that will check the quality of your code and also let you know any loophole or possible security vulnerability.
- Automatic Artifact Generation – It will automatically generate the build artefacts and preserve it. This way you can perform a series of verification and integration testing on the same code. This is really helpful as every artefact have a unique version number attached so you can be sure that the testing is performed on the same artefact which was generated.
- Recreate the Artefacts On-Demand – Every build is version controlled. So in case you need to go back to the old build artefacts, you can do it easily. It is as easy as navigating to the old version and build again.
- Keep Track of All The Stages – You can keep track of all the stage that is performed so far. This gives you a clear picture of the process; Build is a success or not; artefacts generated or not, artefacts uploaded successfully or not; Which tests were performed etc…
Guidelines to Ensure Smooth Integration
There are certain guidelines that we follow in ThoughtWorks that ensures that the integration is smooth.
- Check-in code to the mainline end-of-everyday – Checkin the code that you have worked on at the end of the day.
- Have a suite of tests to validate your changes – There is no use if the code is syntactically correct but disobeys the behaviour of the application. So always make it a habit to write a unit test for the changes you make. Following articles will help you to start with Test Driven Development.
- Fixing the Broken Build Should Be Your Number One Priority – The mantra is – Never leave the office with a broken build. Once more changes are pushed over the broker build the harder it gets to find the bug and resolve it. So make sure you fix the broken build first and then carry on with the development.
Mapping Continous Integration To Microservices
This topic is so vast that it could be a chapter in itself. But I would keep it short and crisp and only talk about different mapping schemes that are used at different size enterprise.
Let’s divide the mapping schemes based on the size of the organization as small, medium and large.
The small enterprise is the one where there is less number of teams (1-3-5).
There is the simplest solution for such an enterprise and that is to use Single Source Code Repository and CI build for all different microservices.
It looks like this:
It has a very simple build model.
Just one monolithic build for all the microservices.
Any check-in to this source code repository will trigger the build for all. It will produce artefacts for all the microservices tied with the same build number.
As you can see in the image all the artefacts are tied to the same build number
A very simple model; Fewer Repositories to worry about; And conceptually simple build;
One commit is all that a developer has to worry about at any given time.
As I said, this will work with a single team in a small enterprise. But with bigger enterprise comes more microservices and more teams. Then this model has significant downsides.
Downsides of this model
- More Build Time – A single line of change in any of the service builds all three services.
- More Artefacts – Change in any of the services will result in the generation of artefacts for all the services. This consumes more disk space.
- Deployment Logics Become Complex – Identifying which service is changed and deploying just that service requires complex logic. You will have to read the commit messages, compare them to see which is changed and then deploy the changed one. It is better to deploy all three artefacts together but that is specifically what we need to avoid.
- Single Point Of Failure – If anyone microservice is broken then it won’t allow others to build either. This will hinder parallel development.
- Difficult for Multiple Teams to Work Together – As every team is dependent on each other, it is hard to manage multiple teams.