Chapter 1. Microservices architecture
Have you ever thought about marching bands? There are groups of brass players, woodwind players, percussion players, and color guards that join together and play their role without being dependent on each other. Any individual player can be replaced or upgraded without disrupting the entire instrumental section.
Microservices are like this: any one part can be replaced without breaking down the entire system.
Let’s take a cinema system as an example. You can always check which movies are showing. You can also check if the movies have been well reviewed, you can reserve a ticket (or two), and you can be notified when new movies are showing (of course, in your favorite genre). As the requirements grow, you can add more features like blacklisting users, or embedding a payment gateway that helps customers when paying for tickets. But in this scenario you have to test the whole system to make sure that changes don’t affect other parts of the system, and you need to take the system offline when making upgrades. With microservices, however, you don’t need to test the entire system and you don’t need to take it offline.
Monolith’s most popular patterns in view of Microservices
There are several design patterns used in a monolith architecture to scale up the system. The most popular patterns are three-tier architectures and MVC. In microservices both patterns are used in order to build a single service or to compose services.
Three-tier architecture
Three-tier architecture separates development based on three layers:
  1. Data Access Layer (DAL) is a layer where we define our entities and their relationships. This is the core of the whole system. Because of the core word, this is the last layer that should be changed or modified.
  2. Business Logic Layer (BLL) is where we put business policies and workflows. It controls whole business events and their responses. Because policies and workflows change from time to time, this layer should dynamically change.
  3. Presentation Layer (UIL) is the upper layer that is seen and interacts with the end user of an app. This layer is dependent on devices, whether they are desktop apps, web apps, or mobile apps.
Three-tier architecture is used to better maintain processes. This architecture is commonly modified and used in microservices. For example, you can put a data access layer and business logic layer in a service level, and the presentation layer in the client level. In the other example, implementing three tiers in level of services, clients only need to fetch requests to display views. This second option is not frequently used.
MVC architecture
Model-View-Controller (MVC) architecture is widely used in popular web-based frameworks like Ruby on Rails and Laravel. Model represents the Data Access Layer and the Business Logic Layer, while View and Controller represent the Presentation Layer. Just like with three tiers architecture, the MVC architecture is often modified and used in microservices.
Microservices answer
Using microservices is not only about chunking the monolith into pieces, because the whole mindset is different. It is much more than just separating layers. Some microservices characteristics may help explain what microservices can and should be.
Bounded Context
Before stepping out into the microservices world, the very first thing to know is bounded context, which allows you to focus on the core context and its logic. It is quite similar to the domain context in the domain design driven approach. Looking back at our example cinema system, you can break the system down into smaller contexts:
  1. Movie service provides detailed information about movies like: movie title, ratings, casts, etc.
  2. Show Time Service is responsible for handling movie schedules in specific theaters and how much it costs.
  3. Booking Service allows customers to book which movie they’d like to watch and when, and reserve their seat for a certain showtime.
  4. Users Service defines information about users. For example, an employee or a customer, name, email, password, etc.
When the requirements grow, like giving recommendations for new releases to our customers, or blacklisting a customer who was caught recording the movie with his/her phone, or even embedding a system with a payment gateway like PayPal, you can just add more services without worrying that it will cause problems with other services.
Small in size
How small is micro in microservices?
Doing microservices is an art, so there are no specific rules about how it is done. But it should be enough to handle the context. The context can be composed of a verb, noun, or even a hybrid of a verb-noun. The small size makes it easier to be replaced or upgraded.
Various platforms
Microservices allow you to deploy services in various platforms. You can deploy a movie service in Python using MongoDB, for example, and deploy a showtime service using PHP and MySql.
Y axis scaling
Microservices are not running multiple-identical copies of an application, instead they split an application into multiple-different services. A common scaling mode is a 3 * 3 dimensional cube, which consists of 18 similar little cubes. Microservices are more like a lego house, which is built upon different types of 3D geometric shapes, like rectangulars or triangular prisms where each prism is responsible for one context.
Ideal environment of microservices
Microservices are not an answer to every problem. There are requirements that allow microservices to run in an ideal environment:
  1. Big Systems: Microservices were created to solve problems for big systems. That’s why a microservices’ architecture, pattern, and technology make sense to cases like Netflix or Spotify. Microservices is prepared to solve problems like crowded traffic, ever-changing requirements, technologies, patterns, and business, along with how to handle different flows of a big system and to be fast and light at the same time. The word big has no particular measurement, but you can say it should be big enough to break down into contexts.
  2. Goal Oriented: Since there is a need for scaling up, services are goal oriented. If a service is designed to focus on one thing, it is then easier to upgrade or even replace the service without breaking the flow, which is the DNA of microservices.
  3. Replaceability: As written above, microservices aim to be replaced or upgraded without interrupting the flow. It’s driving the development process to replace a service instead of maintaining a service. As you know, maintaining a service is the most costly in the development phase.
Communicating with the world
Let’s say you have services built independently, but you need to orchestrate these various platforms of services into a harmony to run a workflow or a business scenario. What is the best way to do this?
Does a different service mean a different engine?
Microservices allow you to put a service in whenever you want to, anywhere. As for the previous case, there is an issue about whether an endpoint should be able to handle multiple requests from various frontend engines. Instead of an obligation to put services in a different engine, we need to actually put it in a different engine.
Let’s say we need to build multiple frontend interfaces for our cinema system:
  1. Responsive web app for browsers
  2. Native Android app
Both of these frontend interfaces need different data content. For example, in an Android app you need to display a customer’s name, a movie showtime list that contains information like title, and show time and price. The web app needs to display more details like a movies’ short description, ratings, and main casts. The questions are:
  1. Should our web app know all of the addresses of our services? And should it make a request for each piece of information as needed?
  2. Is it okay to let our bare services be exposed to all frontend interfaces?
  3. Should the Android app fetch all data, which means the consumption of more bandwidth, when only some data is needed?
Using an API gateway
Implementing an API Gateway as an interface to our services will help solve the problems described in the previous section.
  1. We can wrap data from various services into one response in one request, and at the same time protect our services address from the ‘outside world.’ For example, instead of calling http://users.mycinemas.com/details/me and http://showtime.mycinemas.com/lists , we can just call http://kongcinemas.com/movies/lists .
The scenario of a calling service is a benefit for us. If we’re going to change our services address, only one place needs to be changed (you don’t have to change all interface request addresses).
Instead of making two connections, frontend apps make only one connection through the API Gateway in order to fetch data that is needed by a single app. Besides, all of the exposed addresses are always API Gateway addresses.
  1. An API Gateway also works as an authentication and authorization engine for frontend interfaces, and it can log all of their requests. As for our case, the API Gateway is able to make differences between requests from Android apps or web apps. Feel free to visit Chapter 9 to learn more about this.
  2. An API Gateway allows you to transform or limit data that you need. This then saves bandwidth, prevents malicious action and fake calls, and more.
API Gateway variation
There are many ways of using an API Gateway. You can have one API Gateway for one client or one API Gateway for multiple clients.
A pattern called Backends For Frontends (BFF) has two clients: responsive web apps and native Android apps. It also has two different API gateways. Each of those Gateways provide services for each client. So, when is the right time to use BFF or a single API Gateway?
Let’s say that a responsive web app was built by a web developer team, and a native Android app was built by an Android developer team. Separate teams working on different interfaces might cause bottlenecks in the development process. On the other hand, different interfaces mean different requirements due to device performance. This might cause conflicts while updating requirements, since an API Gateway must be able to handle different requirements in one way. This means that more effort is required to deploy an API Gateway than what every client needs. Changes in backend services needs to be validated by both interface teams before they are implemented.
Let’s look again at our cinema system. The native Android app needs more interactive features. In order to fulfill that purpose, our API Gateway needs have a specific-purpose backend. That’s the ideal time to implement a Backends For Frontends pattern.
Multiple servers for one services
Another usage of the API Gateway is load balancing, which efficiently distributes network traffic across services, making it possible to run multiple servers of services in concurrent time. Let’s say we have three requests for showtime service, and an API Gateway that helps us assign which request should be handle by which services. This means that all requests can get a responses in almost the same time, with no need to wait.
Summary
You should now have a good understanding of microservices, and in the next chapter we will look in more detail at API Gateways and Kong.