This article has been authorized by the author Liu Chao netease cloud community.
Welcome to visit netease Cloud Community to learn more about Netease’s technical product operation experience.
1. Why stateless and containerized
Many applications are split into microservices to carry high concurrency. Often, one process cannot carry such a large amount, so it is necessary to split into multiple groups of processes. Each group of processes carries specific work, and multiple copies are used to jointly bear the traffic according to the pressure of concurrency.
Changing a process to multiple sets of processes, each with multiple copies, requires program modifications to support this distributed architecture. If the architecture does not support this, simply creating multiple copies in the resource layer will not solve the problem.
Many people say that the support of double eleven depends on stacking machines, who can’t? Truly experienced will feel, can rely on the pile machine pile out, are not a problem, afraid of the machine pile up, because of the architecture of the problem, the concurrency is still not up.
The key thing that prevents a monolithic architecture from becoming a distributed one is the handling of state. If all the state is kept locally, either in local memory or on a local hard disk, it creates a bottleneck for the architecture to scale horizontally.
State is divided into distribution, processing and storage. If all information about a user is stored in a process, the user must be distributed to the process during the distribution phase, otherwise the user cannot be processed. However, when a process is under great pressure, it cannot be expanded at all. The newly started process simply cannot handle the data stored in the original process and cannot share the burden.
Therefore, the whole architecture is divided into two parts, stateless part and stateful part, and the part of business logic is often regarded as stateless part, and the state is stored in the stateful middleware, such as cache, database, object storage, big data platform, message queue, etc.
This stateless part can easily scale horizontally, and when distributed by the user, it can easily be distributed to a new process for processing, while the state is saved to the back end. The back-end middleware is stateful. At the beginning of the design of these middleware, the migration, replication, synchronization and other mechanisms of the state during capacity expansion have been taken into account, without the concern of the business layer.
As shown, the architecture is divided into two layers, stateless and stateful.
Containers and microservices are twins, because microservices will split single applications into many smaller applications, so operation and continuous integration will work more, and container technology can solve this problem well. However, before microservitization, it is recommended to containerize first, and before containerization, it is recommended to be stateless first. When the whole process is containerized, the future microservice splitting will come naturally.
Key points of statelessness
I said that for any state, you need to think about distribution, processing, storage.
Data storage mainly includes the following types of data:
-
Session data is mainly stored in memory.
-
Structured data, mainly business logic related
-
File and picture data, which is relatively large, is usually delivered through CDN
-
Unstructured data, such as text, comments, etc
If this data is kept locally and coupled with the business logic, the same user needs to be assigned to the same process when the data is distributed, which affects the horizontal scaling of the architecture.
Data stored in memory, such as sessions, can be stored in an external unified cache.
For business-related data, it should be stored in a unified database. If the performance cannot be supported, read and write separation can be carried out, such as the database design and read and write separation of article microsertization
If performance still holds up, you can use a distributed database.
Data such as files and photos should be stored in unified object storage and preloaded through CDN. For example, the access layer of article micro-service is designed to be isolated from dynamic and static resources
Unstructured data can be stored in a unified search engine, such as ElasticSearch.
If all the data is stored in an external unified storage, the application becomes a stateless application that contains only business logic and can scale smoothly horizontally.
All external unified stores, whether caches, databases, object stores, or search engines, have their own distributed scale-out mechanism.
After statelessness is implemented, stateful clusters can be centralized and deployed across machine rooms to achieve high availability across machine rooms. The stateless parts can be automatically discovered through Dubbo. When a process dies, it can be restarted and repaired automatically. Multiple machine rooms can also be deployed.
Idempotent interface design
However, there is still a legacy problem, is distributed, processing, but not stored data, there will be some in memory, when the process restarts, some data will be lost, so how to do this part of the data?
This part needs to be solved by retry. If the call fails, the preceding process will retry. For example, Dubbo has a retry mechanism. Since retry, the interface needs to be idempotent, that is, the same transaction, two calls to transfer 1 yuan, cannot eventually transfer 2 yuan.
The interface is divided into query, insert, update, delete and other operations.
The query interface itself is idempotent, without special judgment.
For the insert interface, if each data has a unique primary key, the uniqueness of the insert can be guaranteed. If not, an error will be reported.
For the update operation, it is more complicated, divided into several cases.
One is the idempotency of the same interface being called multiple times. On the other hand, the same interface can be used multiple times in a concurrent environment.
In order to keep idempotent, it is often necessary to have an idempotent table, which ensures that each operation is executed only once by passing in idempotent parameters matching the IDS in the idempotent table. In addition, when implementing the final consistency, the interface can be successfully called through repeated retries.
For concurrent conditions, who calls first and who calls later, distributed locks such as Redis and Zookeeper are needed to realize that only one request is executed at the same time. How to ensure that the results of multiple executions are consistent? It is often required to go through a state machine, with each state flowing only once. Optimistic locking, also known as distributed CAS operation, integrates state judgment and update into one statement to ensure atomicity of state flow. Optimistic locking does not guarantee a successful update, and a mechanism is needed to deal with update failures.
Iv. Technical principles of containers
Once stateless, containerization is easy to implement. The immutable infrastructure of containers, as well as the automatic restart and repair of containers based on the container platform, is very smooth because of statelessness.
Key technology a: Dockerfile
For example, the following Dockerfile.
Why use Dockerfile instead of saving the image to generate the image?
In this way, the environment configuration and environment deployment code, Dockerfile maintenance in Git, version control, and through the automatic build process to generate images, and the image is the environment configuration and environment deployment, to modify the environment should be first through Git Dockerfile modification way, That’s IaC.
Key technology two: container image
The container image is stored in layers. For each statement in the Dockerfile, a layer of container image is generated, and so on. Each layer has a UUID.
Container images can be stored in a unified image repository with a version number.
Key technology three: Container runtime
Container runtime, is the container image on top of a writable layer, as seen by the container runtime file system.
Container runtime uses two isolation techniques.
One is a seemingly isolated technique called namespace, where each application in a namespace sees a different IP address, user space, procedure number, and so on.
The other is a segregated technique called cgroup, which means that the entire machine has a lot of CPU and memory, but an application can only use part of it.
cgroup
The basic cloud computing services of netease deeply integrate IaaS, PaaS and container technologies, provide elastic computing, DevOps tool chain and micro-service infrastructure services, help enterprises solve IT, architecture, operation and maintenance problems, and make enterprises more focused on business. As a new-generation cloud computing platform, you can click to try IT for free.
Related articles: Kudu vs HBase