When you are starting to consider building a new product, a new application or refactoring and retrofitting an existing application to make it future proof at one point in time you will most likely consider the use of microservices.
Microservices is a specialization of an implementation approach for service-oriented architectures used to build flexible, independently deployable software systems. Services in a microservice architecture are processes that communicate with each other over a network in order to fulfill a goal. These services use technology-agnostic protocols. The microservices approach is a first realization of SOA that followed the introduction of DevOps and is becoming more popular for building continuously deployed systems.
In a microservices architecture, services should have a small granularity and the protocols should be lightweight. A central microservices property that appears in multiple definitions is that services should be independently deployable. The benefit of distributing different responsibilities of the system into different smaller services is that it enhances the cohesion and decreases the coupling. This makes it easier to change and add functions and qualities to the system at any time. It also allows the architecture of an individual service to emerge through continuous refactoring, and hence reduces the need for a big up-front design and allows for releasing software early and continuously.
Knowing your functionality
Regardless of the fact that you are building a new application from scratch or that you are intending to build upon an existing application and will be retrofitting for the future you will need to understand its functionality. In traditional architecture methods it is vitally important to understand the functionality of your application, however, when moving to a Microservices Architecture it is even more important.
The primary reason why it is important to understand the application functionality and the business use of the application is driven by the fact that it is good practice to break application up into Microservices based upon the functional components.
Traditionally all functionality was captured in an overall monolithic application architecture. With Microservices each functionality can be in theory a separate Microservice.
Whenever starting to architect an application which will be based upon Microservices you will have to make a functional decomposition to break down the complexity and map this on functional areas and functional components and later to services and Microservices.
Functional decomposition is the process of taking a complex process and breaking it down into its smaller, simpler, parts. This might result in the below high level functional decomposition which is represented in a flow.
In a real world application this will be a sub-decomposition of a much larger and much more complex set of processes. The main pitfall is that this is primarily done by developers, who tend to think in solutions. The best way to do a pure functional decomposition is doing it without thinking about how this should be implemented in code (or a system for that matter). This is best done when thinking about the process how it would be done with pen and paper.
After you have defined the functional steps you can break down the steps into the functions you need per step. In this model you can define which technical functions you need to be able to complete a step. As an example, if one of your steps is checking the transportation costs for sending a parcel to a customers shipping location you might need the following technical functions:
- Get combined weight for all products in the order
- Determine shipping box on product sizes
- Get shipping destination
- Get shipping costs based upon weight, box dimensions and destination
- Get customer discount
- Apply customer discount on shipping costs
This will provide you a mapping like shown below as a visual example representation. In reality you will provide the actual function description.
Mapping functional decomposition to services
When you have been able to create a decomposition of your application in both functional steps as well as the functions needed to support the functional step you will be able to start mapping the overlap of technical functions over all the functional steps in your flow. If we take the example of the steps needed to determine the costs for sending a parcel you have the required technical function “get customer discount”. This technical function will be required in multiple steps in an order intake flow.
The below representation shows the mapping of the functional decomposition and finding the double functions in the overall flow.
If you have been able to find the “double”functions you can map them to future microservices. The idea of a microservice is that you can call it from every functional step where it is needed. This holds that you can have it in a central location in your microservices deployment and call it from the functional step when needed.
Sizing your microservice deployment
In essence microservices are, due to the way microservices communicate, ideal to make a high available and highly scalable architecture. As a rule of thumb it is considered a good practice to always deploy a microservice in a high available mode and always have a minimal deployment of two instances of a microservice in your deployment.
Based upon the number of functional steps that use a specific microservice you can take a first guess of the number of instances you need for the microservices. As stated, a default rule every microservice needs to be deployed at least in a dual deployment fashion. If you see that certain microservices are used by multiple functional steps it might be wise to deploy more than only two instances for this specific microservice.
In every case, regardless of the fact you will use microservices, it is a vital step in the thinking process to brake down your your application in functional parts. When developing a microservices based solution the functional decomposition can be used to start mapping the different microservices you will need and align them with the functional steps in your application.