It has been two months since I learned and used Node.js. I used express combined with mongoose to write a web application and a set of RESTful web api. Looking back at the introduction to Node.js on the homepage of the Node.js official website: Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. So what does the non-blocking I/O model mean?
Non-blocking IO model
First of all, IO operations are undoubtedly time-consuming. When the server receives a large number of requests, creating a process or thread for each request also adds additional memory overhead and may waste more time resources.
Since Node.js is event-driven, it uses an event loop to solve the bottleneck problem caused by IO operations. In Node.js, an IO operation usually has a callback function. When the IO operation is completed and returns, this callback function will be called, and the main thread will continue to execute the next code. Let’s simply use an example to illustrate this problem:
request('http://www.google.com', function(error, response, body) { console.log(body); }); console.log('Done!');
The meaning of this code is to make a request to 'http://www.google.com'. When the request returns, the callback function is called to output the response information. Due to the operating mechanism of Node.js, after this code is run, 'Done!' will be output to the console immediately, and then the response information will be output after a period of time.
Event loop event loop
Next, let’s discuss the mechanism of the event loop. First, let’s talk about calling 桟. For example, there is the following piece of code:
function A(arg, func){ var a = arg; func(); console.log('A'); } function B(){ console.log('B'); } A(0, B);
When the code is executed, function A is first pushed into the calling bucket to become the top element of the stack and starts executing A. During the execution process, function B is pushed into the calling bucket to become the top element of the stack. After the execution of B is completed, B After being popped out of the calling stack, A becomes the top element of the stack again. After the execution of A is completed, A is popped out of the calling stack, and the calling stack becomes idle.
There is a message queue in the Javascript runtime, and the message is associated with a callback function. When an event is triggered, if the event has a corresponding callback function, the message will be added to the message queue. .
Looking back at what exactly the event loop loops about, after the code starts executing, functions are continuously pushed into the calling bucket. Take the above example, request is pushed into the calling bucket, and this function will be executed An http request (this http request will be implemented by the underlying module of Node.js). At the same time, the event of request completion is associated with a callback function. The request is popped out of the calling stack, and console.log is pushed into the calling stack to start execution. When the request is completed, the completion event is triggered and a message is added to the message queue. The message queue will first check whether the calling stacker is idle. If the calling stacker is not idle, it will wait until the calling stacker is idle and then The head of the message queue pops up, and the callback function associated with the message is executed.
Summary
The above is a conceptual summary of the non-blocking model and event loop. This event loop mechanism is not unique to Node.js, and the code of Node.js is executed in a single thread. What advantages does it have when facing a large number of concurrent requests?
The above picture shows the architecture diagram of Node.js. There is a module at the bottom of Node.js that is responsible for maintaining the thread pool. When an IO request is issued, the bottom module of Node.js will create a new thread to process the request. , and then return the results to the upper layer after completion. Then, when there are multiple requests, the underlying module of Node.js will use as few threads as possible to complete the most tasks. If there are idle threads, it will continue to be used to do other things, which is what I said earlier. In terms of opening a new process or thread for each request, it is undoubtedly much "smarter" and more efficient.
This article is a summary of learning Node.js. If there are any problems or deficiencies, please feel free to criticize and correct me.