There are
many types of software architectures with their pros and cons. Next, let's talk about the features of the most popular of them and tell you about your transition to microservices.
/ libreshot / PDTypes of software architectures
Layered architecture
This is one of the most common architectures. On its basis, built many large frameworks - Java EE, Drupal, Express. Perhaps the most famous example of this architecture is the
OSI network model.
')
The system is divided into levels, each of which interacts with only two adjacent ones. Therefore, queries to the database, which is usually located at the very end of the interaction chain, pass sequentially through each “layer”.
The architecture
does not imply any mandatory number of levels - there may be three, four, five or more. Three-tier systems are most often used: with the presentation level (client), logic level and data level.
Countless books and articles have been written about multi-tier architecture. And there were different opinions about its advantages and disadvantages.
Pros:Each level of this architecture performs a strictly limited set of functions (which are not repeated from layer to layer) and does not know how the other levels are arranged. Therefore, the “contents” of the levels can be changed without the risk of global conflicts between the layers.
In general, multi-tier applications are so common that special template generators are created for their development. For example,
LASG for Visual Studio offers several code generation methods that automate routine tasks and help build application layers.
Disadvantages:There is a saying in programming that any problem can be solved by adding another level of abstraction. However, this approach may ultimately lead to poor code organization and confuse developers.
This results in another problem - low speed. A lot of information begins to uselessly pass from layer to layer, without using business logic. Sometimes this problem
is called sinkhole anti-pattern - a design pattern when the number of useless operations begins to prevail over useful ones.
Finding bugs in multi-level systems
can also
be difficult . Before getting into the database, information passes through all levels (since the database is the final component). If for some reason this information is damaged (or lost along the way), then in order to find an error it is necessary to analyze each level separately.
Fits good:- To create new applications that need to be deployed quickly. This is a kind of “general purpose pattern”.
When we started working on the internal systems of our virtual infrastructure provider in 1cloud , we used this type of architecture. At the start, we were not faced with the task of creating an IaaS service capable of processing traffic of tens or hundreds of thousands of users. We decided to quickly launch a product on the market and start building up a client base, and solve scaling problems as they arrive (and now we are switching all systems to the microservice architecture, which we will discuss later).
Among the developers there is an opinion that it is not necessary to prepare it for enormous loads from the very first days of the project (write future proof software). Actual requirements for an application or service may differ from those expected, and business goals may change . Therefore, code written with an eye to the distant future runs the risk of becoming a technical debt. - According to O'Reilly, multi-tier architecture is a natural choice for many enterprise applications. Since companies (especially large ones) often share competencies: there is a team responsible for the frontend, there are people who are responsible for the backend, and so on. This leads to the natural division of applications into levels: some developers work on the client, others on logic.
A similar relationship between the structure of the organization and the approaches to developing applications is also dictated by Conway’s law , formulated back in 1967. He says: "In developing any system, organizations are forced to adhere to a scheme that would repeat the structure of communications within the company."
Event-oriented architecture
In this case, the developer prescribes behavior (reactions) for the program when any events occur. An event in the system is considered a significant change in its state.
You can draw an analogy with buying a car in the cabin. When a car finds a new owner, its state changes from “sold” to “sold”. This event starts the process of pre-sale preparation - installation of additional equipment, technical inspection, washing, etc.
An event-driven system typically contains two components: event sources (agents) and their consumers (sinks). Event types are usually also two: an initiating event and an event to which consumers respond.
An example of such an architecture is the Java Swing library. If the class needs to be notified of any event, the developer implements the so-called listener - ActionListener (he “catches” the appropriate event), and appends it to the object that this event can generate.
The Wiki provides the following code for implementing this mechanism:
public class FooPanel extends JPanel implements ActionListener { public FooPanel() { super(); JButton btn = new JButton("Click Me!"); btn.addActionListener(this); this.add(btn); } @Override public void actionPerformed(ActionEvent ae) { System.out.println("Button has been clicked!"); } }
Advantages of architecture:Since applications consist of a large number of asynchronous modules (which do not have information about the implementation of each other), they are easy to scale. Such systems are going as a constructor - no need to prescribe dependencies, just implement a new module. Additionally, the asynchronous model allows for high performance applications.
Disadvantages:The asynchronous nature of such applications complicates debugging. One event can trigger multiple chains of actions at once. If there are many such chains, then it
can be difficult to understand exactly what caused the failure. To solve the problem, one
has to work through complex error handling conditions. This also implies a problem with logging - logs are
difficult to structure.
Suitable for:- Creation of asynchronous systems. This is obvious because the architecture itself consists of a large number of asynchronous modules.
- You can use to create a UI. A web page acts as a container in which each of its components is isolated and responds to certain user actions.
- For organizing the exchange of messages between different information systems.
Micronuclear architecture
This type of architecture consists of two components: the system core and plug-ins. Plug-ins are responsible for business logic, and the kernel manages their loading and unloading.
As an example of the micronuclear architecture in the O'Reilly book
, the Eclipse IDE is
provided . This is a simple editor that opens files, edits them, and starts background processes. But with the addition of plug-ins (for example, the Java compiler), its functionality is expanded.
The microkernel architecture was used in due time by the Symbian operating system for mobile devices (the development was stopped in 2012). In its microkernel there was a task scheduler, memory management systems and drivers, and the file system and components responsible for telephone communications acted as plug-ins.
Advantages of architecture:It is easy to
port an application from one environment to another, since only the microkernel needs to be modified. Separation of high-level policies and low-level mechanisms simplifies system support and ensures its extensibility.
Disadvantages:Application performance is reduced if you connect too many modules. However, it is
problematic to find a balance between the number of plug-ins and the number of microkernel tasks (usually it contains only frequently used code).
It is also difficult to determine in advance (prior to the development of the application) the optimal degree of fragmentation of the microkernel code. And to change the approach later is almost impossible.
Good for:- Creating extensible applications used by a large number of people. For example, the OS for the iPhone has “microkernel” roots - its developers took inspiration from Mach (this is one of the very first examples of a microkernel).
- Creating applications with a clear separation of basic methods and high-level rules.
- Developing systems with a dynamically changing set of rules that have to be updated frequently.
Microservices
Looks like an event-driven architecture and microkernel. But they are used when individual tasks of the application can be easily divided into small functions -
independent services . These services can be written in different programming languages, since they communicate with each other using the REST API (for example, using
JSON or
Thrift ).
In what proportions to divide the code, the developer decides, but Sam Newman (Sam Newman), the author of the book “
Creating Microservices ”, recommends allocating as many lines of code to microservice as the team can play in two weeks. According to him, this will avoid unnecessary "bloat" architecture.
Most often, microservices are run in so-called containers. These containers are available on the network to other microservices and applications, and the orchestration system manages them all: examples include Kubernetes, Docker Swarm, etc.
Advantages:Microservice architecture simplifies application scaling. To introduce a new feature, just write a new service. If the function is no longer needed, microservice can be disabled. Each microservice is a separate project, so work on them is easy to distribute between development teams.
More information about the mechanisms of scaling microservice systems can be found in the book by Martin Abbott (Martin L. Abbott) “The
Art of Scaling ” (The Art of Scalability).
Disadvantages:Difficult to look for errors. Unlike monolithic systems (when all functions are in the same core), it can be difficult to determine why the query “fell”. For details, you have to go to the logs of the “guilty” process (if there are several of them, then the problem is aggravated).
At the same time, there are additional overhead costs for transferring messages between microservices. According to our estimates, the increase in network costs can reach 25%.
Another drawback is the
need to put up with the concept of eventual consistency (
coordination ultimately ). Microservices have their own data stores, which are accessed by other microservices. Information about changes in this data is not distributed instantly through the system. Therefore, there are situations when some microservices (even for a very short period of time) have outdated data.
Where to use:- In large projects with a high load. For example, microservices are used by streaming platforms. Content delivery systems and other ancillary services can be scaled independently from each other, adjusting to changes in load.
- In systems that use "variegated" resources. If one part of the application needs more CPU time, and the second, memory, then it makes sense to divide them into microservices. After that, they can be taken on different machines - with a powerful CPU or a large amount of memory, respectively.
- When security is needed . Since microservices are isolated and communicate via API, it is possible to ensure that only the information that is needed for one or another service will be transmitted. This is important when working with passwords or payment card data.
Why we in 1cloud go to microservices
As we have said, the basis of the services we provide (
private cloud ,
virtual servers ,
object cloud storage , etc.) is a layered architecture. It showed itself from the good side, but now its scaling capabilities have begun to dry up.
We are becoming more and more partners who provide their solutions based on our franchise platform. There are remote sites and services that become difficult to manage from a single point (in particular, our equipment is located in several data centers
in Russia, Kazakhstan and Belarus ).
To make it easier to scale existing functions and implement new features, we
are transferring all our infrastructure to microservices in
1cloud .

We want to separate them into separate modules and, instead of one complex database, get N simple ones. Thus, in the new architecture, each feature will have a separate database. It is much more convenient and efficient in support and development.
We will be able to share the work on services among several developers (to highlight specialization in the company) and effectively scale horizontally - when needed, we will simply connect new microservices.
Our clients will also receive a number of advantages. Since microservices are not connected with each other, then if a specific service fails, only it will be unavailable, all the rest will continue to function normally. At the same time, even if a global drop in our service occurs, the control panel will continue to work.
Customers from Kazakhstan and Belarus (and other countries where we will open representative offices) will notice a significant increase in the speed and responsiveness of the interfaces, since the control panels will be located locally.
What has been done
So far, we have implemented only the first pilot: “Service Monitoring”. The remaining services will be transferred to the new rails at the end of 2018 - the beginning of 2019.
At the same time, the new architecture lays the technological foundation for the next stage - migration to containers. Now we use the Windows infrastructure, and in order to go to the containers, we need to rewrite all the accumulated code on .NetCore and transfer it under the control of Linux.
We are planning to start a new transition at the beginning of 2019 and finish it at the end of next year.
In simple words, what is worth remembering about architecture- Multi-tier architecture - the application is divided into levels, each of which performs a well-defined set of functions. Each level can be modified separately. Among the shortcomings - the low speed of the code and the complexity of finding bugs.
Suitable for developing applications that need to be quickly brought to the market. Often used to create corporate services. - Event-oriented architecture - here the developer prescribes the reaction of the system to any events. For example, if data is received, write it to a file. Applications based on an event-oriented architecture are easy to scale, since all event handlers do not know anything about the implementation of each other. However, debugging of such systems is difficult - one action can cause several chains of actions at once (it is difficult to understand which of them caused the failure).
Used to create asynchronous systems, organization of graphical interfaces and messaging systems. - Micronuclear architecture - consists of two key components: plug-ins and the kernel. Plug-ins are responsible for business logic, and the core is responsible for their loading and unloading. This separation of duties simplifies system support. However, it can affect performance - it directly depends on the number of connected and active modules.
Suitable for developing extensible applications used by a large number of people, and systems with a set of rules that have to be updated frequently (plug-ins are guaranteed to be easy to update). - Microservice architecture - applications are divided into functions - microservices. Each microservice is an independent component with its own business logic. These components communicate with each other using an API. Such applications are easy to develop (it is possible to distribute work among development teams), but it is difficult to debug.
Used in large projects with high loads that require increased security.
What else do we write on the 1cloud blog: