The term "Micro-service" is getting attention these days, some big names are using this style of design. I was introduced to it by looking at Netflix technical publications, which is similar to the industry that I work in, at the moment.
Currently there is no organisation that defines what exactly this design style is, however there seems to be some consensus around what "Micro-services Architecture" is.
Monolithic vs. Microservice
Comparison is usually a nice way for learning a new concept. So let's compare Micro-services Architecture to Monolithic.
A Monolithic application is single unit application. Think about a web application, HTML/Javascript client side, a web server, which receives client requests, and consolidated it's database to generate html and return to client. We want to focus on server side.
The server side application is a monolithic executable, a bulk. Updating the application means updating the executable and or database. If the application goes down, non of the features of this application are accessible. usually it is all written in the same programming language, and runs in the same process(, communication between modules is in the same process). And finally to scale horizontally you just need to run more instances of that application ( i.e.: load-balancers and more web servers).
When
Monolithic architecture can be successful, however in some situations the characteristics of this style of design may not be what you want, They are NOT so compatible with :
- Horizontal scaling: It may not mean having to scale all the features of your application. Only some areas of your application may need to be scaled and each by a different factor and at different times.
- Different areas of your application may be written easier and with better performance using a different language or development paradigm(Nodejs, go, python, C++,..), and platform.
- Development cycles need to be independent: A team has to wait for all others to finish(design, develop, test,... ) before they can deploy their work.
- Organised around business capability rather than organisation's communication path ways.. For example instead of having a UI, Middleware, and database team for the whole application. You will have a team of each category around each service or business capability.
Characteristics
In Micro-services the flavour is around product mentality, rather than project. In this style there is an ongoing work in the software and the team is more focused on linking business capabilities and providing more features for the customer. This is even extended to the fact that development team is responsible for deploying and maintaining the running instances.
It seems that micro-services are about smart endpoints and simple pipes. Consider restful http services, versus ESB(enterprise Service Bus)that can transform, apply business rules and orchestrate activities, using WS- distributed transaction protocols . In micro-services each service is conceptually decoupled and features are as cohesive as possible. In a more complicated case some sort of message queuing may be use, i.e.: RabbitQ.
Micro-services are Asynchronous, this increases performance, and respects the distributed mode considering congestions, failures,.. .
Data modelling and persistence is decentralised, meaning that each service models the world in their own relevant terms, and persist them in any format using the technology that makes the most sense for them, RDBMS, NoSql, SQL server, MongoDB, Cassandra,.. .
Automation and monitoring, are more advanced that monolithic applications.The pipeline that starts with building and unit testing and ends in deployment to production, needs to be automated. In Netflix they have the concept of bakery, where they have template instances, then they bake an service update into a machine, and it is released all with or without click of a button.
In a world that many services are running you need to know: about the statistics of your services, how they perform, track messages, and monitor the health of the services.
A consequence of using services as components, is that applications need to be designed so that they can tolerate the failure of services. Any service call could fail due to unavailability of the supplier, the client has to respond to this as gracefully as possible.
This is where some patterns have emerged : tolerant reader, throttling,.. .
There are some limited number of domain / contexts that each developer can have in mind work with, using micro-services is compatible with how many contexts a developer can handle, and different skills they need to have. So with smaller teams and more focused there are people with more skills, and less communication overhead.
Service Granularity
There are disagreements about how many lines of code a service needs to be, however this seems to be irrelevant. What matters is the level of granularity we are prepared to introduce. This may relate to lines of code, but that's irrelevant to the idea of micro-services.
Please refer to the diagram on the top observing how some factors change as we move from and monolithic application towards having more and more services.
Modelling the right way is what need to be cared about. Domain Driven Design approach (bounded context) could be a useful approach in this style of design.
Challenges
In a way, with micro-services architecture some concepts will be pushed into runtime rather than development or build time. This raises issues if you are not prepared for them, specially after you have released to production.
However these can be mitigated by using some techniques and tools.
Versioning: Each micro-service can have it's own development and release cycle. Consider service A depends on Service B(version 1). What happens when Service B (version 2) is released?
Contracts: To make it even harder, service development might be like silos, one team not knowing what the other ones are providing, how can Service A know what to expect service B? We are not talking about interface, but the "needs and provides services".
Testing: When testing, service A is going to mock service B, how do developers know what is the behaviour for service B that they need to mock?
Service Boundaries: Another issue is how to define service boundaries? a part of the answer is the service granularity, and the bigger part of the answer could be domain driven design(bounded context).
Transactions: The concept of a transaction which used to run in a process, will changes as we go distributed. It adds overhead to your services.
Monitoring, and tracking : you will need tools for monitoring the health of the services, to see how they are doing, to see which ones are failing.
A mature micro-service style application needs to have tools to spin new servers automatically or manually in a matter of few minutes if not seconds.
Summary
Micro-services are the trend these days, they stand against monolithic applications, they are another way of designing applications, with some pros and cons.
The amount of preparation you need to do to get ready for micro-services is considerable, continuous delivery,automation, testing strategy, deployment ... requires you to have a top shape product and supporting infrastructure.
Start simple( with a monolithic application), and break chunks off it bit by bit and move them to micro-services, however apply . You need to confirm that the business model works first, then try to move.
References: Martin Fowler, Netflix articles, Ryan Murray & John Napier.