Problem
Before going into the details about microservices, it is important to understand the background of another architecture known as a monolithic architecture. A monolith application is generally a large one that has tightly coupled components. The challenges of monolithic application include the following:
- It is hard to scale a monolithic application. Since all the components are tightly coupled, larger modifications are needed.
- If the business aims to adopt a different technology then it is not viable to adopt it, due to the presence of certain constraints.
- Automation is a hard nut to crack with monolithic applications.
- Modern-day coding conventions and solutions are also difficult to implement.
What Are Microservices?
One of the easiest definitions of microservices is explained by Sam Newman.
Small autonomous services that work together
Microservices can be seen as a self-contained solution that helps in the provision of distinct business functionalities for applications. Various microservices may appear as separate but their combination as a whole runs the entire application smoothly.
For instance, suppose there is an e-commerce website. For simplicity purposes, we will divide its business processes into two modules. Firstly, we have the order module that helps customers to order a product by selecting customized options. Secondly, we have the processing module that will communicate with the back-end and verify the banking and other relevant details of the customer. In a monolithic application, a change in the order module means a change in the processing module too.
However, if we are talking about microservices, then essentially we separate these mini processes. In microservices architecture, we have an order microservice and a processing microservice. These microservices can exchange information through a protocol or interface like REST. Generally, this communication is stateless which means that there is no dependence on the state of a component. Additionally, each of the microservice is independent and manages its own data.
Why Use Microservices?
Work on the Immediate Problem
In the case of a monolithic application, an upgrade, repair or modification means tinkering with the entire codebase of the application. This dilemma is solved through the emergence of the microservices. Microservices help to focus and modify only the relevant component of the example. For example, if the above-mentioned order microservice needs a change in its business logic, then only its microservice needs to be worked upon. Restructuring or recoding might not seem like a difficult problem for small applications but in the case of enterprise applications, they consume a great deal of time and resources.
Organization of Teams
Often IT managers are unable to properly utilize their developers as they are unsure about how to divide the tasks of different modules. Subsequently, developers from different teams struggle in the debugging and modification of the code. With microservices, each service can be allocated a small team. Due to its loose coupling, developers are empowered to focus on their own services. Consequently, they are also saved from consulting with other teams for the updating of single business functionality.
Different Languages
Often a problem in an enterprise application is the selection of a programming language and framework. Sometimes, PHP is good for certain business functionality while sometimes Java’s security is the need of the hour. Luckily, the microservices architecture allows the writing of code for each service in the language of the developer’s choice. Since all the services communicate with each other through standardized protocols, hence microservices provide flexibility.
How Microservices Improve on the Previous Architectures?
There is a misunderstanding regarding the nature of microservices architecture. Some people believe that the microservices divide an application’s web, business and data models. This approach is not dissimilar to the vision behind the previous out-dated architectures. However, this is a faulty analysis.
Instead, each microservice manages its own data model. Hence, only the team of a specific microservice can change its behavior. Another feature that separates microservices from others is stateless communication. Stateless communication helps in the scalability of the application as each pair of the request and response is handled independently.
Example
For a practical implementation, let’s take a look at an example of Hello World application using Microservices in Java. We will create a HelloWorldService class.
class HelloWorldService {
public String greet() {
return “Hello, World!”;
}
The above-mentioned code can be written in different Java environments. For example, for our console application, we can write the following.
class Starter {
HelloWorldService helloWorldService = new HelloWorldService();
public static void main(String[] args) {
String message = helloWorldService.greet();
System.out.println(message);
}
}
For java servlets, we can write the following lines of code.
class HelloWorldServlet extends HttpServlet {
HelloWorldService helloWorldService = new HelloWorldService();
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String message = helloWorldService.greet();
response.getWriter().println(message);
}
}
For coding the controllers of Spring MVC applications, we will have to write the following piece of code.
@Controller
class HelloWorldController {
HelloWorldService helloWorldService = new HelloWorldService();
@RequestMapping(“/helloWorld”)
public String greet() {
String message = helloWorldService.greet();
return message;
}
}
Now, we have to solve the service issues that can be either related to the entire service’s unavailability or its ineffectiveness in returning an appropriate response. Service unavailability is mainly the client’s headache to deal with. With code written with the help of frameworks like unirest.io, clients are able to manage the service unavailability better.
Future<HttpResponse<JsonNode>>future= Unirest.post(“HTTP://helloworld.myservices.local/greet”).header(“accept”,”application/json”).asJsonAsync(new Callback<JsonNode>() {
public void failed(UnirestException e) { //tell them UI folks that the request went south
}
public void completed(HttpResponse<JsonNode> response) { //extract data from response and fulfill it’s destiny }
public void cancelled() {//shot a note to UI dept that the request got cancelled } } );
In the case the service fails, you can use the following code for the response.
{
“status”:”ok”,
”message”:”Hello, World!”
}
The status attributes help to show the correct nature of a response.
Final Thoughts
Since its emergence, microservices have reinvented several enterprise applications and helped save developers from a great deal of complexities. Now, developers do not need to reduplicate their codebases. The working of entire projects has been improved vastly this way.