Today modern R&D is getting more complex by the minute.
Every other day a new framework, language, design comes up and we need to learn them. We do so because we want the best out of our product and we will become better programmers and above all good designers.
Some of those phenomenons are easy to grasp and some aren’t.
Today I would like to share with you about the fact that there are many back-end frameworks, networking protocols, integration methodologies and so much more… that pretty much gives us awesome tools to work with but may give the rise to complex software architecture designs.
We of course as a programmer, the beast of self-improvement who learns all the time about programming, do need to know how to encounter that issue with the best result as we can, especially when developing backend applications.
This entire topic of developing back-end applications can be breathtaking and hard to grasp at first but once you get the hang of it you’re good to go!
Now… we do have a huge buzzword which is called micro-services.
I had a talk with my friend the other day considering the subject, and while we were talking I understood that my entire knowledge on this subject is something that I wrapped up from reading many articles/posts online or attained it from friends and colleagues or just practicing while working.
What I’m trying to say, is with the only experience of developing complex backend applications you get insights into how to do so efficiently.
In this post, I would like to shortly describe what micro-services are, what are the rules of thumbs for them, and the main core values which will allow us to understand how to design them.
If you do know what is back-end development you can start your reading but if not I suggest you read this
Let’s go back a little
When usually we wanted to develop some backend applications, we had to choose our programming language and the framework.
We did chose these two, we chose them correspondingly to the right task, so the framework and language helped us to solve our problem in the most fastest and efficient way.
After we chose our tools for fighting the army of Sauron(Lord of the rings fan xD), we now start to develop our backend.
Something that we’re very popular, is creating a single application which holds the entire logic of the application.
That approach is called monolith.
Monolith is described as putting everything in one place, which is the opposite of microservices.
We’re talking about this because it’s important to understand why monolith is not good 🙂
Imagine you have an amazing lego dragon you built, but you want to upgrade it with new parts. Because everything is coupled all together it’s hard to do so, unless you break it apart until you completely put it all back together.
Again image, doing so with software which could be very complex, and add up altogether to break it apart, get to know each piece, do your change, and put it all back together.
Could be frustrating ain’t it? 😉
In time of the development comes the complexity, and it could be sophisticated algorithms, databases, complex architecture, security, network streaming, network file sharing, and more…
When dealing with those issues and a short time to deliver amazing products to our clients or ourselves, we can do mistakes which will cost us in the future, and they aren’t being done on purpose.
It’s only because we focus on the current situation and resolution of the product, and it happens because we’re humans, and that’s OK when we learn from those experiences for the best.
So what is the big secret?
Well… in one short sentence… it’s developing your back-end application to be non-monolithic which is having a service for every area of functionality, but that’s not the only thing.
We’ve seen what is Monolith.
Some of you might be thinking, what if I’ll use design patterns to make my application to be non coupled. Could that be any good?
It could be. But what if you need to do an extreme redesign to your application, and you have more people working with you on the same project?
You might be thinking on confronting merge conflicts, and re-updating on the new features while you work, and I feel you, I know it can be breathtaking 🙂
To what we’ve described there a lot more of painful areas but it’s the main one, but just for the fun lets imagine you have some kind of functionality that cannot be scaled up and down, but others can.
Or cases you need to give extra care to functionality A but not functionality B.
So as you can see, there are a lot of cases that can lead to a monolith application to be cumbersome regarding the evolution of our application.
But how can we overcome this?!
We need to delimit each area of functionality in our application to a single service.
You might be saying “Ido is really that’s all?! that can’t be true!”, well you’re right because that’s the headlight and we will focus on some points further.
In simple points
As said before when trying to implement our server using microservices, we should focus on building small services, which each one does the only thing he’s responsible for and no more.
The popular way to communicate between services is by using HTTP and message brokers for asynchronous communication cases.
Each service that we develop should be treated as a black box because it does what it does and we don’t care how.
Regarding databases, it’s not a recommendation but like a bible rule.
Each service only uses its own database!
No service should access another service database, even if it’s reading!
Imagine when you need to understand some quite complex flow, which you don’t understand how service A gets information about the service B database.
So what you do? You go to service B API you wrote, and try to understand how does service B provides for service A his data.
But then! you see the access the database directly.
That’s why we need to use the HTTP API of service B because he’s responsible for his data and not others.
When we will follow these rules, we can split up the services between many teams and personal, which will allow them to keep proceeding forward without affecting other teams and their services, which is a great benefit for everyone.
Resiliency and downtime
Another major aspect that microservice architecture needs to take care of, is to be able to recover from errors fast and efficiently.
Let’s say we have one service in a 10 services architecture, that suffers from an exception and because of that our architecture might fall apart.
If it falls down and doesn’t provide any service or at least a fallback mechanism as a response, that service has some work to be done with.
Because of that, you need to strive that your services will be designed in ways that you have fallback mechanisms, so everything will not fall apart once something fails.
I can’t tell you how to design your services or how to implement them because each application has its own complex architecture.
I do can suggest is to get someone from another team or service, who got a fresh and new perspective, that could look at your service in a new way.
That way, we can find the errors that could happen at start and design our service in a better way, and along the way work with a colleague, share insights and get to know them better.
More benefits
As you probably can see by now, there are many benefits to using microservices. Some of them might be obviously clear and some might not, so I do wish to mention a few more of them:
- Deploy independently — Because each logic is wrapped in its own service, we can deploy each service on his own without any downtime for other services.
- Isolated responsibility — Each service has to take care of only his own logic, which leads to a much more simple and short codebase. The result is that we don’t have any magic code which we don’t understand.
- Scale — We can do up or downscaling as we wish, without any consideration to other services and only to our service needs.
- Future extensions — Due to other services treating each other as a “black box”, we can do improvements to our services in any wished manner without harming any other logical flows.
Popular approaches
We talked about developing the service and all, but is there a popular design for them?
We do have and they are:
- API Gateway — A service that gets requests from web/mobile applications and even the service. He’s responsible to forward the request to the right service who will respond back to the one who made the request.
In the end, this tool/service wraps all of our URLs, security to approach them (and even more) in a singular place. - Service mesh — All services register themselves to a singular place/service. Of course, we can also pre-configure them all inside that service. This way all services that need another service request that service URL, so afterward, they simply talk to the service they wished in the first place.
Of course that for every product or company, there are their own unique traits and needs, which design the entire services architecture that they build, so making a design that fits them all, is quite hard to do, especially that microservices design is pretty new.
I think in time, new designs and approaches will appear, and as with development tools that go through changes, this will too.
How can we design a microservices architecture?
I don’t want to simply babel about what is microservices architecture and leave you with nothing, so what I want to do an overview of is how to design one.
Usually, when a programmer receives an awesome new project he’s drooling with joy and can’t wait to start working on it.
What usually everyone does is jumping straight for the design patterns, language specifications(C/C++, Java, Python, etc…), cool frameworks, build tools, and more…
What I do suggest in my opinion at least is think that the entire application you want to write actually exists and provides what you would expect.
What you need to do now, is take each part you know the application does and start splitting them apart to unified services.
After we split apart our application into smaller units.
We need to be creative for this one, and think of ways how each service could fall or not provide what he needs to accomplish his tasks, and also think of ways the entire architecture could change by it in terms of:
- How do my services talk with each other — protocols, local shared data on the machine, authentication mechanism, message brokers, and more…
- What my services needs to get their work done perfectly?
In some cases, our services need some pre-configured data or events that occurred in the past to prepare them for any kind of service. - What data is stored for each service — files, configurations, database connections, 3rd party resources.
- If service A falls or to much traffic goes through him, how does that affect our services architecture in terms of durability, response time, failures, and more…
- How can we design fallback mechanisms when something went wrong, so we could still provide what we need to, or provide some response that would still be worth working with, and later on take care of it more efficiently.
The reason for those questions is because of those questions, you may rise situations that could occur in the future and you can prevent horrors from happening, like asking you to stay at work when the weekend has arrived 🙂
As we talked before, getting a friend and hearing his way of thinking of what we came up with, could help a lot.
Conclusion
I can go more on this subject, but we will continue, we will only hit subjects that will confuse this subject even more in order to understand micro-services architecture, but I hope you got the point.
Microservices, are a way of design that has grown pretty much in the last years, and I think will keep growing due to its crucial need.
Each company today is giving their special way of developing them, so I think as everything that grows, we will see new things in the future regarding the subject.
In some organizations, they don’t use this design implementation because of deprecated code or any other mainframe applications, because its rather hard to decompose the applications to be non-monolithic.
This may cause problems with deployment or development down the road, which may cost money for our startup or the company we work in.
Because of all that, we should always strive to design our code better so we become better programmers by learning what not to do 🙂
I hope you had a great time reading this piece, and if you have any further questions I would be delighted to answer them.
Also, if you have any opinions or suggestions for improving this piece, I would like to hear 🙂
Thank you all for your time and I wish you a great journey!