Hello, Habr. Right now, OTUS is accepting applications for a new cohort of the course . As we approach the start of the course, I want to share my author article with you.
Introduction
Choosing an architectural style is one of the fundamental technical decisions when building an information system. In this series of articles, I propose to explore the most popular architectural styles for building applications and answer the question of when each architectural style is the most preferable. Throughout the discussion, I will try to establish a logical chain that explains the evolution of architectural styles from monoliths to microservices.
A Bit of History
If you ask developers, "What are microservices for?", you will get a variety of answers. You will hear that microservices improve scalability, simplify code understanding, enhance fault tolerance, and sometimes you may hear that they allow for 'cleaning up code'. Let’s refer to history to understand the goal behind the emergence of microservices.
In brief, microservices, as we understand them today, originated as follows: in 2011, James Lewis, analyzing the work of various companies, noted the emergence of a new pattern called 'micro-app', which optimized SOA in terms of speeding up service deployment. A little later, in 2012, at an architectural summit, the pattern was renamed to microservice. Thus, the original goal of implementing microservices was to improve the notorious time to market.
In the 'hype wave', microservices gained popularity in 2015. According to some studies, no conference was complete without a presentation on microservices. Moreover, some conferences were dedicated solely to microservices. Nowadays, many projects start with this architectural style, and if a project contains tons of legacy code, there is certainly an active migration to microservices.
Despite the above, still a relatively small number of developers can define the concept of 'microservice'. But we will discuss this a bit later...
Monolith
The architectural style that contrasts with microservices is the monolith (or 'all-in-one'). There's probably no need to explain what a monolith is, so I will immediately list the disadvantages of this architectural style that initiated further development in architectural styles: size, coupling, deployment, scalability, reliability, and rigidity. Below, I suggest considering each of these disadvantages individually.
Size
A monolith is very large. It typically communicates with a very large database. The application becomes too big for a single developer to comprehend effectively. Only those who have spent a considerable amount of time with this code can work well with the monolith, while newcomers will spend a lot of time trying to understand it, and even then it’s not guaranteed they will succeed. Usually, there is some sort of 'conditional' senior developer who knows the monolith fairly well and keeps a close watch on new developers for about a year or so. Naturally, this conditional senior becomes a single point of failure, and their departure can lead to the downfall of the monolith.
Coupling
A monolith can be described as a 'big ball of mud'; changes to it can lead to unpredictable consequences. By making changes in one area, you can inadvertently damage another area of the monolith (the classic case of 'scratching your ear and breaking something off'). This is due to the fact that components within the monolith have very complex and, importantly, non-obvious interrelations.
Deployment
Deploying a monolith, due to the complex relationships between its components, is a long process with its own rituals. Such rituals are often not fully standardized and are passed down 'orally'.
Scalability
Modules of the monolith may have conflicting resource needs, which necessitates finding a compromise in terms of hardware. Imagine that your monolith consists of services A and B. Service A is demanding in terms of hard disk size, while service B requires more RAM. In this case, either the machine on which the monolith is installed must meet the requirements of both services, or one of the services will have to be manually disabled.
Another example (more classic): Service A is much more popular than Service B, so you want 100 instances of Service A and 10 instances of Service B. Again, there are two options: either we deploy 100 full-fledged monoliths, or we have to manually disable some instances of Service B on certain ones.
Reliability
Since all services are together, if the monolith fails, all services go down at once. In fact, this might not be so bad; at least there won't be partial failures in a distributed system. However, on the flip side, due to an error in a functionality that is used by 0.001% of users, you could lose all users of your system.
Rigidity
Due to the size of the monolith, it is difficult to transition to new technologies. As a result, retaining that elusive senior developer becomes an essential task. The chosen technology stack at the start of the project may become a block to the product's development.
Conclusion
Next time, we will discuss how people tried to solve these issues by moving towards components and SOA.
Read more:
Source: habr.com
